diff --git a/go.mod b/go.mod index 2eef7e8..906c271 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rotisserie/eris v0.1.1 github.com/servicemeshinterface/smi-sdk-go v0.4.1 - github.com/solo-io/skv2 v0.36.3 + github.com/solo-io/skv2 v0.36.6-0.20240322145206-690e2f50c2e5 istio.io/client-go v1.20.1 istio.io/istio v0.0.0-20231207195727-552626bd81f6 k8s.io/api v0.28.3 @@ -169,4 +169,7 @@ require ( // go: istio.io/istio@v0.0.0-20231207195727-552626bd81f6 requires github.com/imdario/mergo@v1.0.0: parsing go.mod: // module declares its path as: dario.cat/mergo // but was required as: github.com/imdario/mergo -replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.5 +replace ( + github.com/imdario/mergo => github.com/imdario/mergo v0.3.5 + github.com/solo-io/skv2 => ../skv2 +) diff --git a/go.sum b/go.sum index ede3664..c92dcf6 100644 --- a/go.sum +++ b/go.sum @@ -908,6 +908,14 @@ github.com/solo-io/protoc-gen-ext v0.0.18 h1:zSAL8NzWpJUGYoA5IyjHiKASNyHjR0uxBQ7 github.com/solo-io/protoc-gen-ext v0.0.18/go.mod h1:iGyCvmKmhJNXs5MgBcYFBF0om7LDnCVD2WwhOZGnqeA= github.com/solo-io/skv2 v0.36.3 h1:qy2gOlmjVlSBSLan1+VUsEVolw3breFnti8pdKyWbXs= github.com/solo-io/skv2 v0.36.3/go.mod h1:0GKILLOrQiTKvGsf7UEFZJiDxJHrp0yKJQ6NbHzn+vY= +github.com/solo-io/skv2 v0.36.6-0.20240321214511-d656e5746aa5 h1:ftOMZrcLyCKUCE/DBUTraP4K1OH6VO7MqcwrfJ3hUcE= +github.com/solo-io/skv2 v0.36.6-0.20240321214511-d656e5746aa5/go.mod h1:0GKILLOrQiTKvGsf7UEFZJiDxJHrp0yKJQ6NbHzn+vY= +github.com/solo-io/skv2 v0.36.6-0.20240321221313-072b52964242 h1:GcToAOffyrVZW5qbdLI8GbXt/KmXNR7LpKdMUjRFG3Q= +github.com/solo-io/skv2 v0.36.6-0.20240321221313-072b52964242/go.mod h1:0GKILLOrQiTKvGsf7UEFZJiDxJHrp0yKJQ6NbHzn+vY= +github.com/solo-io/skv2 v0.36.6-0.20240322135812-94192f5279ae h1:qB6fyGKK/hFsMP2Yd29qfTN/Skl1suo1KvYWyf6kjzc= +github.com/solo-io/skv2 v0.36.6-0.20240322135812-94192f5279ae/go.mod h1:0GKILLOrQiTKvGsf7UEFZJiDxJHrp0yKJQ6NbHzn+vY= +github.com/solo-io/skv2 v0.36.6-0.20240322145206-690e2f50c2e5 h1:yopWOho8SfVU63b0asPU+570g2Jn/N9mdXbMUpKq1xM= +github.com/solo-io/skv2 v0.36.6-0.20240322145206-690e2f50c2e5/go.mod h1:0GKILLOrQiTKvGsf7UEFZJiDxJHrp0yKJQ6NbHzn+vY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/mocks/sets.go b/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/mocks/sets.go index cee52f3..e09c19b 100644 --- a/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/mocks/sets.go +++ b/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockMeshSet is a mock of MeshSet interface. @@ -135,6 +136,34 @@ func (mr *MockMeshSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockMeshSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockMeshSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockMeshSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockMeshSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockMeshSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockMeshSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockMeshSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockMeshSet) Has(mesh ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockVirtualServiceSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockVirtualServiceSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockVirtualServiceSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockVirtualServiceSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockVirtualServiceSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockVirtualServiceSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockVirtualServiceSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockVirtualServiceSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockVirtualServiceSet) Has(virtualService ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockVirtualNodeSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockVirtualNodeSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockVirtualNodeSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockVirtualNodeSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockVirtualNodeSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockVirtualNodeSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockVirtualNodeSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockVirtualNodeSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockVirtualNodeSet) Has(virtualNode ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -903,6 +988,34 @@ func (mr *MockVirtualRouterSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockVirtualRouterSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockVirtualRouterSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockVirtualRouterSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockVirtualRouterSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockVirtualRouterSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockVirtualRouterSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockVirtualRouterSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockVirtualRouterSet) Has(virtualRouter ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1159,6 +1272,34 @@ func (mr *MockVirtualGatewaySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockVirtualGatewaySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockVirtualGatewaySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockVirtualGatewaySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockVirtualGatewaySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockVirtualGatewaySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockVirtualGatewaySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockVirtualGatewaySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockVirtualGatewaySet) Has(virtualGateway ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1415,6 +1556,34 @@ func (mr *MockGatewayRouteSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockGatewayRouteSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockGatewayRouteSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockGatewayRouteSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockGatewayRouteSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockGatewayRouteSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockGatewayRouteSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockGatewayRouteSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockGatewayRouteSet) Has(gatewayRoute ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/sets.go b/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/sets.go index f7cd4d3..f2e5003 100644 --- a/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/sets.go +++ b/pkg/api/appmesh/appmesh.k8s.aws/v1beta2/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type MeshSet interface { @@ -48,30 +50,98 @@ type MeshSet interface { Delta(newSet MeshSet) sksets.ResourceDelta // Create a deep copy of the current MeshSet Clone() MeshSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericMeshSet(meshList []*appmesh_k8s_aws_v1beta2.Mesh) sksets.ResourceSet { +func makeGenericMeshSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + meshList []*appmesh_k8s_aws_v1beta2.Mesh, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range meshList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type meshSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewMeshSet(meshList ...*appmesh_k8s_aws_v1beta2.Mesh) MeshSet { - return &meshSet{set: makeGenericMeshSet(meshList)} +func NewMeshSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + meshList ...*appmesh_k8s_aws_v1beta2.Mesh, +) MeshSet { + return &meshSet{ + set: makeGenericMeshSet(sortFunc, equalityFunc, meshList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewMeshSetFromList(meshList *appmesh_k8s_aws_v1beta2.MeshList) MeshSet { +func NewMeshSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + meshList *appmesh_k8s_aws_v1beta2.MeshList, +) MeshSet { list := make([]*appmesh_k8s_aws_v1beta2.Mesh, 0, len(meshList.Items)) for idx := range meshList.Items { list = append(list, &meshList.Items[idx]) } - return &meshSet{set: makeGenericMeshSet(list)} + return &meshSet{ + set: makeGenericMeshSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *meshSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *meshSet) Union(set MeshSet) MeshSet { if s == nil { return set } - return NewMeshSet(append(s.List(), set.List()...)...) + return NewMeshSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *meshSet) Difference(set MeshSet) MeshSet { @@ -179,7 +249,11 @@ func (s *meshSet) Difference(set MeshSet) MeshSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &meshSet{set: newSet} + return &meshSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *meshSet) Intersection(set MeshSet) MeshSet { @@ -191,7 +265,7 @@ func (s *meshSet) Intersection(set MeshSet) MeshSet { for _, obj := range newSet.List() { meshList = append(meshList, obj.(*appmesh_k8s_aws_v1beta2.Mesh)) } - return NewMeshSet(meshList...) + return NewMeshSet(s.sortFunc, s.equalityFunc, meshList...) } func (s *meshSet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.Mesh, error) { @@ -233,7 +307,63 @@ func (s *meshSet) Clone() MeshSet { if s == nil { return nil } - return &meshSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.Mesh{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &meshSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *meshSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *meshSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type VirtualServiceSet interface { @@ -271,30 +401,98 @@ type VirtualServiceSet interface { Delta(newSet VirtualServiceSet) sksets.ResourceDelta // Create a deep copy of the current VirtualServiceSet Clone() VirtualServiceSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericVirtualServiceSet(virtualServiceList []*appmesh_k8s_aws_v1beta2.VirtualService) sksets.ResourceSet { +func makeGenericVirtualServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList []*appmesh_k8s_aws_v1beta2.VirtualService, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range virtualServiceList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type virtualServiceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewVirtualServiceSet(virtualServiceList ...*appmesh_k8s_aws_v1beta2.VirtualService) VirtualServiceSet { - return &virtualServiceSet{set: makeGenericVirtualServiceSet(virtualServiceList)} +func NewVirtualServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList ...*appmesh_k8s_aws_v1beta2.VirtualService, +) VirtualServiceSet { + return &virtualServiceSet{ + set: makeGenericVirtualServiceSet(sortFunc, equalityFunc, virtualServiceList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewVirtualServiceSetFromList(virtualServiceList *appmesh_k8s_aws_v1beta2.VirtualServiceList) VirtualServiceSet { +func NewVirtualServiceSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList *appmesh_k8s_aws_v1beta2.VirtualServiceList, +) VirtualServiceSet { list := make([]*appmesh_k8s_aws_v1beta2.VirtualService, 0, len(virtualServiceList.Items)) for idx := range virtualServiceList.Items { list = append(list, &virtualServiceList.Items[idx]) } - return &virtualServiceSet{set: makeGenericVirtualServiceSet(list)} + return &virtualServiceSet{ + set: makeGenericVirtualServiceSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *virtualServiceSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *virtualServiceSet) Union(set VirtualServiceSet) VirtualServiceSet { if s == nil { return set } - return NewVirtualServiceSet(append(s.List(), set.List()...)...) + return NewVirtualServiceSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *virtualServiceSet) Difference(set VirtualServiceSet) VirtualServiceSet { @@ -402,7 +600,11 @@ func (s *virtualServiceSet) Difference(set VirtualServiceSet) VirtualServiceSet return set } newSet := s.Generic().Difference(set.Generic()) - return &virtualServiceSet{set: newSet} + return &virtualServiceSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *virtualServiceSet) Intersection(set VirtualServiceSet) VirtualServiceSet { @@ -414,7 +616,7 @@ func (s *virtualServiceSet) Intersection(set VirtualServiceSet) VirtualServiceSe for _, obj := range newSet.List() { virtualServiceList = append(virtualServiceList, obj.(*appmesh_k8s_aws_v1beta2.VirtualService)) } - return NewVirtualServiceSet(virtualServiceList...) + return NewVirtualServiceSet(s.sortFunc, s.equalityFunc, virtualServiceList...) } func (s *virtualServiceSet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.VirtualService, error) { @@ -456,7 +658,63 @@ func (s *virtualServiceSet) Clone() VirtualServiceSet { if s == nil { return nil } - return &virtualServiceSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &virtualServiceSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *virtualServiceSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *virtualServiceSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type VirtualNodeSet interface { @@ -494,30 +752,98 @@ type VirtualNodeSet interface { Delta(newSet VirtualNodeSet) sksets.ResourceDelta // Create a deep copy of the current VirtualNodeSet Clone() VirtualNodeSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericVirtualNodeSet(virtualNodeList []*appmesh_k8s_aws_v1beta2.VirtualNode) sksets.ResourceSet { +func makeGenericVirtualNodeSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualNodeList []*appmesh_k8s_aws_v1beta2.VirtualNode, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range virtualNodeList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type virtualNodeSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewVirtualNodeSet(virtualNodeList ...*appmesh_k8s_aws_v1beta2.VirtualNode) VirtualNodeSet { - return &virtualNodeSet{set: makeGenericVirtualNodeSet(virtualNodeList)} +func NewVirtualNodeSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualNodeList ...*appmesh_k8s_aws_v1beta2.VirtualNode, +) VirtualNodeSet { + return &virtualNodeSet{ + set: makeGenericVirtualNodeSet(sortFunc, equalityFunc, virtualNodeList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewVirtualNodeSetFromList(virtualNodeList *appmesh_k8s_aws_v1beta2.VirtualNodeList) VirtualNodeSet { +func NewVirtualNodeSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualNodeList *appmesh_k8s_aws_v1beta2.VirtualNodeList, +) VirtualNodeSet { list := make([]*appmesh_k8s_aws_v1beta2.VirtualNode, 0, len(virtualNodeList.Items)) for idx := range virtualNodeList.Items { list = append(list, &virtualNodeList.Items[idx]) } - return &virtualNodeSet{set: makeGenericVirtualNodeSet(list)} + return &virtualNodeSet{ + set: makeGenericVirtualNodeSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *virtualNodeSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *virtualNodeSet) Union(set VirtualNodeSet) VirtualNodeSet { if s == nil { return set } - return NewVirtualNodeSet(append(s.List(), set.List()...)...) + return NewVirtualNodeSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *virtualNodeSet) Difference(set VirtualNodeSet) VirtualNodeSet { @@ -625,7 +951,11 @@ func (s *virtualNodeSet) Difference(set VirtualNodeSet) VirtualNodeSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &virtualNodeSet{set: newSet} + return &virtualNodeSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *virtualNodeSet) Intersection(set VirtualNodeSet) VirtualNodeSet { @@ -637,7 +967,7 @@ func (s *virtualNodeSet) Intersection(set VirtualNodeSet) VirtualNodeSet { for _, obj := range newSet.List() { virtualNodeList = append(virtualNodeList, obj.(*appmesh_k8s_aws_v1beta2.VirtualNode)) } - return NewVirtualNodeSet(virtualNodeList...) + return NewVirtualNodeSet(s.sortFunc, s.equalityFunc, virtualNodeList...) } func (s *virtualNodeSet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.VirtualNode, error) { @@ -679,7 +1009,63 @@ func (s *virtualNodeSet) Clone() VirtualNodeSet { if s == nil { return nil } - return &virtualNodeSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualNode{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &virtualNodeSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *virtualNodeSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *virtualNodeSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type VirtualRouterSet interface { @@ -717,30 +1103,98 @@ type VirtualRouterSet interface { Delta(newSet VirtualRouterSet) sksets.ResourceDelta // Create a deep copy of the current VirtualRouterSet Clone() VirtualRouterSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericVirtualRouterSet(virtualRouterList []*appmesh_k8s_aws_v1beta2.VirtualRouter) sksets.ResourceSet { +func makeGenericVirtualRouterSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualRouterList []*appmesh_k8s_aws_v1beta2.VirtualRouter, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range virtualRouterList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type virtualRouterSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewVirtualRouterSet(virtualRouterList ...*appmesh_k8s_aws_v1beta2.VirtualRouter) VirtualRouterSet { - return &virtualRouterSet{set: makeGenericVirtualRouterSet(virtualRouterList)} +func NewVirtualRouterSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualRouterList ...*appmesh_k8s_aws_v1beta2.VirtualRouter, +) VirtualRouterSet { + return &virtualRouterSet{ + set: makeGenericVirtualRouterSet(sortFunc, equalityFunc, virtualRouterList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewVirtualRouterSetFromList(virtualRouterList *appmesh_k8s_aws_v1beta2.VirtualRouterList) VirtualRouterSet { +func NewVirtualRouterSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualRouterList *appmesh_k8s_aws_v1beta2.VirtualRouterList, +) VirtualRouterSet { list := make([]*appmesh_k8s_aws_v1beta2.VirtualRouter, 0, len(virtualRouterList.Items)) for idx := range virtualRouterList.Items { list = append(list, &virtualRouterList.Items[idx]) } - return &virtualRouterSet{set: makeGenericVirtualRouterSet(list)} + return &virtualRouterSet{ + set: makeGenericVirtualRouterSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *virtualRouterSet) Keys() sets.String { @@ -840,7 +1294,7 @@ func (s *virtualRouterSet) Union(set VirtualRouterSet) VirtualRouterSet { if s == nil { return set } - return NewVirtualRouterSet(append(s.List(), set.List()...)...) + return NewVirtualRouterSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *virtualRouterSet) Difference(set VirtualRouterSet) VirtualRouterSet { @@ -848,7 +1302,11 @@ func (s *virtualRouterSet) Difference(set VirtualRouterSet) VirtualRouterSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &virtualRouterSet{set: newSet} + return &virtualRouterSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *virtualRouterSet) Intersection(set VirtualRouterSet) VirtualRouterSet { @@ -860,7 +1318,7 @@ func (s *virtualRouterSet) Intersection(set VirtualRouterSet) VirtualRouterSet { for _, obj := range newSet.List() { virtualRouterList = append(virtualRouterList, obj.(*appmesh_k8s_aws_v1beta2.VirtualRouter)) } - return NewVirtualRouterSet(virtualRouterList...) + return NewVirtualRouterSet(s.sortFunc, s.equalityFunc, virtualRouterList...) } func (s *virtualRouterSet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.VirtualRouter, error) { @@ -902,7 +1360,63 @@ func (s *virtualRouterSet) Clone() VirtualRouterSet { if s == nil { return nil } - return &virtualRouterSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualRouter{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &virtualRouterSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *virtualRouterSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *virtualRouterSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type VirtualGatewaySet interface { @@ -940,30 +1454,98 @@ type VirtualGatewaySet interface { Delta(newSet VirtualGatewaySet) sksets.ResourceDelta // Create a deep copy of the current VirtualGatewaySet Clone() VirtualGatewaySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericVirtualGatewaySet(virtualGatewayList []*appmesh_k8s_aws_v1beta2.VirtualGateway) sksets.ResourceSet { +func makeGenericVirtualGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualGatewayList []*appmesh_k8s_aws_v1beta2.VirtualGateway, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range virtualGatewayList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type virtualGatewaySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewVirtualGatewaySet(virtualGatewayList ...*appmesh_k8s_aws_v1beta2.VirtualGateway) VirtualGatewaySet { - return &virtualGatewaySet{set: makeGenericVirtualGatewaySet(virtualGatewayList)} +func NewVirtualGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualGatewayList ...*appmesh_k8s_aws_v1beta2.VirtualGateway, +) VirtualGatewaySet { + return &virtualGatewaySet{ + set: makeGenericVirtualGatewaySet(sortFunc, equalityFunc, virtualGatewayList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewVirtualGatewaySetFromList(virtualGatewayList *appmesh_k8s_aws_v1beta2.VirtualGatewayList) VirtualGatewaySet { +func NewVirtualGatewaySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualGatewayList *appmesh_k8s_aws_v1beta2.VirtualGatewayList, +) VirtualGatewaySet { list := make([]*appmesh_k8s_aws_v1beta2.VirtualGateway, 0, len(virtualGatewayList.Items)) for idx := range virtualGatewayList.Items { list = append(list, &virtualGatewayList.Items[idx]) } - return &virtualGatewaySet{set: makeGenericVirtualGatewaySet(list)} + return &virtualGatewaySet{ + set: makeGenericVirtualGatewaySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *virtualGatewaySet) Keys() sets.String { @@ -1063,7 +1645,7 @@ func (s *virtualGatewaySet) Union(set VirtualGatewaySet) VirtualGatewaySet { if s == nil { return set } - return NewVirtualGatewaySet(append(s.List(), set.List()...)...) + return NewVirtualGatewaySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *virtualGatewaySet) Difference(set VirtualGatewaySet) VirtualGatewaySet { @@ -1071,7 +1653,11 @@ func (s *virtualGatewaySet) Difference(set VirtualGatewaySet) VirtualGatewaySet return set } newSet := s.Generic().Difference(set.Generic()) - return &virtualGatewaySet{set: newSet} + return &virtualGatewaySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *virtualGatewaySet) Intersection(set VirtualGatewaySet) VirtualGatewaySet { @@ -1083,7 +1669,7 @@ func (s *virtualGatewaySet) Intersection(set VirtualGatewaySet) VirtualGatewaySe for _, obj := range newSet.List() { virtualGatewayList = append(virtualGatewayList, obj.(*appmesh_k8s_aws_v1beta2.VirtualGateway)) } - return NewVirtualGatewaySet(virtualGatewayList...) + return NewVirtualGatewaySet(s.sortFunc, s.equalityFunc, virtualGatewayList...) } func (s *virtualGatewaySet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.VirtualGateway, error) { @@ -1125,7 +1711,63 @@ func (s *virtualGatewaySet) Clone() VirtualGatewaySet { if s == nil { return nil } - return &virtualGatewaySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.VirtualGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &virtualGatewaySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *virtualGatewaySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *virtualGatewaySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type GatewayRouteSet interface { @@ -1163,30 +1805,98 @@ type GatewayRouteSet interface { Delta(newSet GatewayRouteSet) sksets.ResourceDelta // Create a deep copy of the current GatewayRouteSet Clone() GatewayRouteSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericGatewayRouteSet(gatewayRouteList []*appmesh_k8s_aws_v1beta2.GatewayRoute) sksets.ResourceSet { +func makeGenericGatewayRouteSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayRouteList []*appmesh_k8s_aws_v1beta2.GatewayRoute, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range gatewayRouteList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type gatewayRouteSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewGatewayRouteSet(gatewayRouteList ...*appmesh_k8s_aws_v1beta2.GatewayRoute) GatewayRouteSet { - return &gatewayRouteSet{set: makeGenericGatewayRouteSet(gatewayRouteList)} +func NewGatewayRouteSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayRouteList ...*appmesh_k8s_aws_v1beta2.GatewayRoute, +) GatewayRouteSet { + return &gatewayRouteSet{ + set: makeGenericGatewayRouteSet(sortFunc, equalityFunc, gatewayRouteList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewGatewayRouteSetFromList(gatewayRouteList *appmesh_k8s_aws_v1beta2.GatewayRouteList) GatewayRouteSet { +func NewGatewayRouteSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayRouteList *appmesh_k8s_aws_v1beta2.GatewayRouteList, +) GatewayRouteSet { list := make([]*appmesh_k8s_aws_v1beta2.GatewayRoute, 0, len(gatewayRouteList.Items)) for idx := range gatewayRouteList.Items { list = append(list, &gatewayRouteList.Items[idx]) } - return &gatewayRouteSet{set: makeGenericGatewayRouteSet(list)} + return &gatewayRouteSet{ + set: makeGenericGatewayRouteSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *gatewayRouteSet) Keys() sets.String { @@ -1286,7 +1996,7 @@ func (s *gatewayRouteSet) Union(set GatewayRouteSet) GatewayRouteSet { if s == nil { return set } - return NewGatewayRouteSet(append(s.List(), set.List()...)...) + return NewGatewayRouteSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *gatewayRouteSet) Difference(set GatewayRouteSet) GatewayRouteSet { @@ -1294,7 +2004,11 @@ func (s *gatewayRouteSet) Difference(set GatewayRouteSet) GatewayRouteSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &gatewayRouteSet{set: newSet} + return &gatewayRouteSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *gatewayRouteSet) Intersection(set GatewayRouteSet) GatewayRouteSet { @@ -1306,7 +2020,7 @@ func (s *gatewayRouteSet) Intersection(set GatewayRouteSet) GatewayRouteSet { for _, obj := range newSet.List() { gatewayRouteList = append(gatewayRouteList, obj.(*appmesh_k8s_aws_v1beta2.GatewayRoute)) } - return NewGatewayRouteSet(gatewayRouteList...) + return NewGatewayRouteSet(s.sortFunc, s.equalityFunc, gatewayRouteList...) } func (s *gatewayRouteSet) Find(id ezkube.ResourceId) (*appmesh_k8s_aws_v1beta2.GatewayRoute, error) { @@ -1348,5 +2062,61 @@ func (s *gatewayRouteSet) Clone() GatewayRouteSet { if s == nil { return nil } - return &gatewayRouteSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &appmesh_k8s_aws_v1beta2.GatewayRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &gatewayRouteSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *gatewayRouteSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *gatewayRouteSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/cilium/cilium.io/v2/sets/mocks/sets.go b/pkg/api/cilium/cilium.io/v2/sets/mocks/sets.go index 5e4a05c..807c73a 100644 --- a/pkg/api/cilium/cilium.io/v2/sets/mocks/sets.go +++ b/pkg/api/cilium/cilium.io/v2/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockCiliumNetworkPolicySet is a mock of CiliumNetworkPolicySet interface. @@ -135,6 +136,34 @@ func (mr *MockCiliumNetworkPolicySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockCiliumNetworkPolicySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockCiliumNetworkPolicySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockCiliumNetworkPolicySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockCiliumNetworkPolicySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockCiliumNetworkPolicySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockCiliumNetworkPolicySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockCiliumNetworkPolicySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockCiliumNetworkPolicySet) Has(ciliumNetworkPolicy ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/cilium/cilium.io/v2/sets/sets.go b/pkg/api/cilium/cilium.io/v2/sets/sets.go index e5259d1..9db479d 100644 --- a/pkg/api/cilium/cilium.io/v2/sets/sets.go +++ b/pkg/api/cilium/cilium.io/v2/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type CiliumNetworkPolicySet interface { @@ -48,30 +50,98 @@ type CiliumNetworkPolicySet interface { Delta(newSet CiliumNetworkPolicySet) sksets.ResourceDelta // Create a deep copy of the current CiliumNetworkPolicySet Clone() CiliumNetworkPolicySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericCiliumNetworkPolicySet(ciliumNetworkPolicyList []*cilium_io_v2.CiliumNetworkPolicy) sksets.ResourceSet { +func makeGenericCiliumNetworkPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + ciliumNetworkPolicyList []*cilium_io_v2.CiliumNetworkPolicy, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range ciliumNetworkPolicyList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type ciliumNetworkPolicySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewCiliumNetworkPolicySet(ciliumNetworkPolicyList ...*cilium_io_v2.CiliumNetworkPolicy) CiliumNetworkPolicySet { - return &ciliumNetworkPolicySet{set: makeGenericCiliumNetworkPolicySet(ciliumNetworkPolicyList)} +func NewCiliumNetworkPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + ciliumNetworkPolicyList ...*cilium_io_v2.CiliumNetworkPolicy, +) CiliumNetworkPolicySet { + return &ciliumNetworkPolicySet{ + set: makeGenericCiliumNetworkPolicySet(sortFunc, equalityFunc, ciliumNetworkPolicyList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewCiliumNetworkPolicySetFromList(ciliumNetworkPolicyList *cilium_io_v2.CiliumNetworkPolicyList) CiliumNetworkPolicySet { +func NewCiliumNetworkPolicySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + ciliumNetworkPolicyList *cilium_io_v2.CiliumNetworkPolicyList, +) CiliumNetworkPolicySet { list := make([]*cilium_io_v2.CiliumNetworkPolicy, 0, len(ciliumNetworkPolicyList.Items)) for idx := range ciliumNetworkPolicyList.Items { list = append(list, &ciliumNetworkPolicyList.Items[idx]) } - return &ciliumNetworkPolicySet{set: makeGenericCiliumNetworkPolicySet(list)} + return &ciliumNetworkPolicySet{ + set: makeGenericCiliumNetworkPolicySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *ciliumNetworkPolicySet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *ciliumNetworkPolicySet) Union(set CiliumNetworkPolicySet) CiliumNetwork if s == nil { return set } - return NewCiliumNetworkPolicySet(append(s.List(), set.List()...)...) + return NewCiliumNetworkPolicySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *ciliumNetworkPolicySet) Difference(set CiliumNetworkPolicySet) CiliumNetworkPolicySet { @@ -179,7 +249,11 @@ func (s *ciliumNetworkPolicySet) Difference(set CiliumNetworkPolicySet) CiliumNe return set } newSet := s.Generic().Difference(set.Generic()) - return &ciliumNetworkPolicySet{set: newSet} + return &ciliumNetworkPolicySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *ciliumNetworkPolicySet) Intersection(set CiliumNetworkPolicySet) CiliumNetworkPolicySet { @@ -191,7 +265,7 @@ func (s *ciliumNetworkPolicySet) Intersection(set CiliumNetworkPolicySet) Cilium for _, obj := range newSet.List() { ciliumNetworkPolicyList = append(ciliumNetworkPolicyList, obj.(*cilium_io_v2.CiliumNetworkPolicy)) } - return NewCiliumNetworkPolicySet(ciliumNetworkPolicyList...) + return NewCiliumNetworkPolicySet(s.sortFunc, s.equalityFunc, ciliumNetworkPolicyList...) } func (s *ciliumNetworkPolicySet) Find(id ezkube.ResourceId) (*cilium_io_v2.CiliumNetworkPolicy, error) { @@ -233,5 +307,61 @@ func (s *ciliumNetworkPolicySet) Clone() CiliumNetworkPolicySet { if s == nil { return nil } - return &ciliumNetworkPolicySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &cilium_io_v2.CiliumNetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &ciliumNetworkPolicySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *ciliumNetworkPolicySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *ciliumNetworkPolicySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/extensions.istio.io/v1alpha1/sets/mocks/sets.go b/pkg/api/istio/extensions.istio.io/v1alpha1/sets/mocks/sets.go index 48b8887..5c5694b 100644 --- a/pkg/api/istio/extensions.istio.io/v1alpha1/sets/mocks/sets.go +++ b/pkg/api/istio/extensions.istio.io/v1alpha1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1alpha1 "istio.io/client-go/pkg/apis/extensions/v1alpha1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockWasmPluginSet is a mock of WasmPluginSet interface. @@ -135,6 +136,34 @@ func (mr *MockWasmPluginSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockWasmPluginSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockWasmPluginSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockWasmPluginSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockWasmPluginSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockWasmPluginSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockWasmPluginSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockWasmPluginSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockWasmPluginSet) Has(wasmPlugin ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/extensions.istio.io/v1alpha1/sets/sets.go b/pkg/api/istio/extensions.istio.io/v1alpha1/sets/sets.go index c56ebe0..b6f6b8e 100644 --- a/pkg/api/istio/extensions.istio.io/v1alpha1/sets/sets.go +++ b/pkg/api/istio/extensions.istio.io/v1alpha1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type WasmPluginSet interface { @@ -48,30 +50,98 @@ type WasmPluginSet interface { Delta(newSet WasmPluginSet) sksets.ResourceDelta // Create a deep copy of the current WasmPluginSet Clone() WasmPluginSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericWasmPluginSet(wasmPluginList []*extensions_istio_io_v1alpha1.WasmPlugin) sksets.ResourceSet { +func makeGenericWasmPluginSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + wasmPluginList []*extensions_istio_io_v1alpha1.WasmPlugin, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range wasmPluginList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type wasmPluginSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewWasmPluginSet(wasmPluginList ...*extensions_istio_io_v1alpha1.WasmPlugin) WasmPluginSet { - return &wasmPluginSet{set: makeGenericWasmPluginSet(wasmPluginList)} +func NewWasmPluginSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + wasmPluginList ...*extensions_istio_io_v1alpha1.WasmPlugin, +) WasmPluginSet { + return &wasmPluginSet{ + set: makeGenericWasmPluginSet(sortFunc, equalityFunc, wasmPluginList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewWasmPluginSetFromList(wasmPluginList *extensions_istio_io_v1alpha1.WasmPluginList) WasmPluginSet { +func NewWasmPluginSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + wasmPluginList *extensions_istio_io_v1alpha1.WasmPluginList, +) WasmPluginSet { list := make([]*extensions_istio_io_v1alpha1.WasmPlugin, 0, len(wasmPluginList.Items)) for idx := range wasmPluginList.Items { list = append(list, wasmPluginList.Items[idx]) } - return &wasmPluginSet{set: makeGenericWasmPluginSet(list)} + return &wasmPluginSet{ + set: makeGenericWasmPluginSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *wasmPluginSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *wasmPluginSet) Union(set WasmPluginSet) WasmPluginSet { if s == nil { return set } - return NewWasmPluginSet(append(s.List(), set.List()...)...) + return NewWasmPluginSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *wasmPluginSet) Difference(set WasmPluginSet) WasmPluginSet { @@ -179,7 +249,11 @@ func (s *wasmPluginSet) Difference(set WasmPluginSet) WasmPluginSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &wasmPluginSet{set: newSet} + return &wasmPluginSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *wasmPluginSet) Intersection(set WasmPluginSet) WasmPluginSet { @@ -191,7 +265,7 @@ func (s *wasmPluginSet) Intersection(set WasmPluginSet) WasmPluginSet { for _, obj := range newSet.List() { wasmPluginList = append(wasmPluginList, obj.(*extensions_istio_io_v1alpha1.WasmPlugin)) } - return NewWasmPluginSet(wasmPluginList...) + return NewWasmPluginSet(s.sortFunc, s.equalityFunc, wasmPluginList...) } func (s *wasmPluginSet) Find(id ezkube.ResourceId) (*extensions_istio_io_v1alpha1.WasmPlugin, error) { @@ -233,5 +307,61 @@ func (s *wasmPluginSet) Clone() WasmPluginSet { if s == nil { return nil } - return &wasmPluginSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &extensions_istio_io_v1alpha1.WasmPlugin{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &wasmPluginSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *wasmPluginSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *wasmPluginSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/install.istio.io/v1alpha1/sets/mocks/sets.go b/pkg/api/istio/install.istio.io/v1alpha1/sets/mocks/sets.go index 06f7aa6..f8b3b7e 100644 --- a/pkg/api/istio/install.istio.io/v1alpha1/sets/mocks/sets.go +++ b/pkg/api/istio/install.istio.io/v1alpha1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockIstioOperatorSet is a mock of IstioOperatorSet interface. @@ -135,6 +136,34 @@ func (mr *MockIstioOperatorSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockIstioOperatorSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockIstioOperatorSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockIstioOperatorSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockIstioOperatorSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockIstioOperatorSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockIstioOperatorSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockIstioOperatorSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockIstioOperatorSet) Has(istioOperator ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/install.istio.io/v1alpha1/sets/sets.go b/pkg/api/istio/install.istio.io/v1alpha1/sets/sets.go index 4b00542..9d9e14e 100644 --- a/pkg/api/istio/install.istio.io/v1alpha1/sets/sets.go +++ b/pkg/api/istio/install.istio.io/v1alpha1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type IstioOperatorSet interface { @@ -48,30 +50,98 @@ type IstioOperatorSet interface { Delta(newSet IstioOperatorSet) sksets.ResourceDelta // Create a deep copy of the current IstioOperatorSet Clone() IstioOperatorSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericIstioOperatorSet(istioOperatorList []*install_istio_io_v1alpha1.IstioOperator) sksets.ResourceSet { +func makeGenericIstioOperatorSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + istioOperatorList []*install_istio_io_v1alpha1.IstioOperator, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range istioOperatorList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type istioOperatorSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewIstioOperatorSet(istioOperatorList ...*install_istio_io_v1alpha1.IstioOperator) IstioOperatorSet { - return &istioOperatorSet{set: makeGenericIstioOperatorSet(istioOperatorList)} +func NewIstioOperatorSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + istioOperatorList ...*install_istio_io_v1alpha1.IstioOperator, +) IstioOperatorSet { + return &istioOperatorSet{ + set: makeGenericIstioOperatorSet(sortFunc, equalityFunc, istioOperatorList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewIstioOperatorSetFromList(istioOperatorList *install_istio_io_v1alpha1.IstioOperatorList) IstioOperatorSet { +func NewIstioOperatorSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + istioOperatorList *install_istio_io_v1alpha1.IstioOperatorList, +) IstioOperatorSet { list := make([]*install_istio_io_v1alpha1.IstioOperator, 0, len(istioOperatorList.Items)) for idx := range istioOperatorList.Items { list = append(list, &istioOperatorList.Items[idx]) } - return &istioOperatorSet{set: makeGenericIstioOperatorSet(list)} + return &istioOperatorSet{ + set: makeGenericIstioOperatorSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *istioOperatorSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *istioOperatorSet) Union(set IstioOperatorSet) IstioOperatorSet { if s == nil { return set } - return NewIstioOperatorSet(append(s.List(), set.List()...)...) + return NewIstioOperatorSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *istioOperatorSet) Difference(set IstioOperatorSet) IstioOperatorSet { @@ -179,7 +249,11 @@ func (s *istioOperatorSet) Difference(set IstioOperatorSet) IstioOperatorSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &istioOperatorSet{set: newSet} + return &istioOperatorSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *istioOperatorSet) Intersection(set IstioOperatorSet) IstioOperatorSet { @@ -191,7 +265,7 @@ func (s *istioOperatorSet) Intersection(set IstioOperatorSet) IstioOperatorSet { for _, obj := range newSet.List() { istioOperatorList = append(istioOperatorList, obj.(*install_istio_io_v1alpha1.IstioOperator)) } - return NewIstioOperatorSet(istioOperatorList...) + return NewIstioOperatorSet(s.sortFunc, s.equalityFunc, istioOperatorList...) } func (s *istioOperatorSet) Find(id ezkube.ResourceId) (*install_istio_io_v1alpha1.IstioOperator, error) { @@ -233,5 +307,61 @@ func (s *istioOperatorSet) Clone() IstioOperatorSet { if s == nil { return nil } - return &istioOperatorSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &install_istio_io_v1alpha1.IstioOperator{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &istioOperatorSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *istioOperatorSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *istioOperatorSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/networking.istio.io/v1alpha3/sets/mocks/sets.go b/pkg/api/istio/networking.istio.io/v1alpha3/sets/mocks/sets.go index b7ef7a1..b53a188 100644 --- a/pkg/api/istio/networking.istio.io/v1alpha3/sets/mocks/sets.go +++ b/pkg/api/istio/networking.istio.io/v1alpha3/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockEnvoyFilterSet is a mock of EnvoyFilterSet interface. @@ -135,6 +136,34 @@ func (mr *MockEnvoyFilterSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockEnvoyFilterSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockEnvoyFilterSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockEnvoyFilterSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockEnvoyFilterSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockEnvoyFilterSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockEnvoyFilterSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockEnvoyFilterSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockEnvoyFilterSet) Has(envoyFilter ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/networking.istio.io/v1alpha3/sets/sets.go b/pkg/api/istio/networking.istio.io/v1alpha3/sets/sets.go index ca75601..0163f2d 100644 --- a/pkg/api/istio/networking.istio.io/v1alpha3/sets/sets.go +++ b/pkg/api/istio/networking.istio.io/v1alpha3/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type EnvoyFilterSet interface { @@ -48,30 +50,98 @@ type EnvoyFilterSet interface { Delta(newSet EnvoyFilterSet) sksets.ResourceDelta // Create a deep copy of the current EnvoyFilterSet Clone() EnvoyFilterSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericEnvoyFilterSet(envoyFilterList []*networking_istio_io_v1alpha3.EnvoyFilter) sksets.ResourceSet { +func makeGenericEnvoyFilterSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + envoyFilterList []*networking_istio_io_v1alpha3.EnvoyFilter, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range envoyFilterList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type envoyFilterSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewEnvoyFilterSet(envoyFilterList ...*networking_istio_io_v1alpha3.EnvoyFilter) EnvoyFilterSet { - return &envoyFilterSet{set: makeGenericEnvoyFilterSet(envoyFilterList)} +func NewEnvoyFilterSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + envoyFilterList ...*networking_istio_io_v1alpha3.EnvoyFilter, +) EnvoyFilterSet { + return &envoyFilterSet{ + set: makeGenericEnvoyFilterSet(sortFunc, equalityFunc, envoyFilterList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewEnvoyFilterSetFromList(envoyFilterList *networking_istio_io_v1alpha3.EnvoyFilterList) EnvoyFilterSet { +func NewEnvoyFilterSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + envoyFilterList *networking_istio_io_v1alpha3.EnvoyFilterList, +) EnvoyFilterSet { list := make([]*networking_istio_io_v1alpha3.EnvoyFilter, 0, len(envoyFilterList.Items)) for idx := range envoyFilterList.Items { list = append(list, envoyFilterList.Items[idx]) } - return &envoyFilterSet{set: makeGenericEnvoyFilterSet(list)} + return &envoyFilterSet{ + set: makeGenericEnvoyFilterSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *envoyFilterSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *envoyFilterSet) Union(set EnvoyFilterSet) EnvoyFilterSet { if s == nil { return set } - return NewEnvoyFilterSet(append(s.List(), set.List()...)...) + return NewEnvoyFilterSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *envoyFilterSet) Difference(set EnvoyFilterSet) EnvoyFilterSet { @@ -179,7 +249,11 @@ func (s *envoyFilterSet) Difference(set EnvoyFilterSet) EnvoyFilterSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &envoyFilterSet{set: newSet} + return &envoyFilterSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *envoyFilterSet) Intersection(set EnvoyFilterSet) EnvoyFilterSet { @@ -191,7 +265,7 @@ func (s *envoyFilterSet) Intersection(set EnvoyFilterSet) EnvoyFilterSet { for _, obj := range newSet.List() { envoyFilterList = append(envoyFilterList, obj.(*networking_istio_io_v1alpha3.EnvoyFilter)) } - return NewEnvoyFilterSet(envoyFilterList...) + return NewEnvoyFilterSet(s.sortFunc, s.equalityFunc, envoyFilterList...) } func (s *envoyFilterSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1alpha3.EnvoyFilter, error) { @@ -233,5 +307,61 @@ func (s *envoyFilterSet) Clone() EnvoyFilterSet { if s == nil { return nil } - return &envoyFilterSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1alpha3.EnvoyFilter{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &envoyFilterSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *envoyFilterSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *envoyFilterSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/networking.istio.io/v1beta1/sets/mocks/sets.go b/pkg/api/istio/networking.istio.io/v1beta1/sets/mocks/sets.go index dc15a4a..eb4a4d7 100644 --- a/pkg/api/istio/networking.istio.io/v1beta1/sets/mocks/sets.go +++ b/pkg/api/istio/networking.istio.io/v1beta1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockDestinationRuleSet is a mock of DestinationRuleSet interface. @@ -135,6 +136,34 @@ func (mr *MockDestinationRuleSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockDestinationRuleSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockDestinationRuleSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockDestinationRuleSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockDestinationRuleSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockDestinationRuleSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockDestinationRuleSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockDestinationRuleSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockDestinationRuleSet) Has(destinationRule ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockGatewaySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockGatewaySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockGatewaySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockGatewaySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockGatewaySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockGatewaySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockGatewaySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockGatewaySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockGatewaySet) Has(gateway ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockProxyConfigSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockProxyConfigSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockProxyConfigSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockProxyConfigSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockProxyConfigSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockProxyConfigSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockProxyConfigSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockProxyConfigSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockProxyConfigSet) Has(proxyConfig ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -903,6 +988,34 @@ func (mr *MockServiceEntrySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockServiceEntrySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockServiceEntrySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockServiceEntrySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockServiceEntrySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockServiceEntrySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockServiceEntrySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockServiceEntrySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockServiceEntrySet) Has(serviceEntry ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1159,6 +1272,34 @@ func (mr *MockWorkloadEntrySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockWorkloadEntrySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockWorkloadEntrySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockWorkloadEntrySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockWorkloadEntrySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockWorkloadEntrySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockWorkloadEntrySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockWorkloadEntrySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockWorkloadEntrySet) Has(workloadEntry ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1415,6 +1556,34 @@ func (mr *MockWorkloadGroupSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockWorkloadGroupSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockWorkloadGroupSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockWorkloadGroupSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockWorkloadGroupSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockWorkloadGroupSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockWorkloadGroupSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockWorkloadGroupSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockWorkloadGroupSet) Has(workloadGroup ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1671,6 +1840,34 @@ func (mr *MockVirtualServiceSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockVirtualServiceSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockVirtualServiceSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockVirtualServiceSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockVirtualServiceSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockVirtualServiceSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockVirtualServiceSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockVirtualServiceSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockVirtualServiceSet) Has(virtualService ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1927,6 +2124,34 @@ func (mr *MockSidecarSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockSidecarSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockSidecarSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockSidecarSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockSidecarSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockSidecarSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockSidecarSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockSidecarSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockSidecarSet) Has(sidecar ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/networking.istio.io/v1beta1/sets/sets.go b/pkg/api/istio/networking.istio.io/v1beta1/sets/sets.go index 1920e5a..c88ccc4 100644 --- a/pkg/api/istio/networking.istio.io/v1beta1/sets/sets.go +++ b/pkg/api/istio/networking.istio.io/v1beta1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type DestinationRuleSet interface { @@ -48,30 +50,98 @@ type DestinationRuleSet interface { Delta(newSet DestinationRuleSet) sksets.ResourceDelta // Create a deep copy of the current DestinationRuleSet Clone() DestinationRuleSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericDestinationRuleSet(destinationRuleList []*networking_istio_io_v1beta1.DestinationRule) sksets.ResourceSet { +func makeGenericDestinationRuleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + destinationRuleList []*networking_istio_io_v1beta1.DestinationRule, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range destinationRuleList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type destinationRuleSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewDestinationRuleSet(destinationRuleList ...*networking_istio_io_v1beta1.DestinationRule) DestinationRuleSet { - return &destinationRuleSet{set: makeGenericDestinationRuleSet(destinationRuleList)} +func NewDestinationRuleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + destinationRuleList ...*networking_istio_io_v1beta1.DestinationRule, +) DestinationRuleSet { + return &destinationRuleSet{ + set: makeGenericDestinationRuleSet(sortFunc, equalityFunc, destinationRuleList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewDestinationRuleSetFromList(destinationRuleList *networking_istio_io_v1beta1.DestinationRuleList) DestinationRuleSet { +func NewDestinationRuleSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + destinationRuleList *networking_istio_io_v1beta1.DestinationRuleList, +) DestinationRuleSet { list := make([]*networking_istio_io_v1beta1.DestinationRule, 0, len(destinationRuleList.Items)) for idx := range destinationRuleList.Items { list = append(list, destinationRuleList.Items[idx]) } - return &destinationRuleSet{set: makeGenericDestinationRuleSet(list)} + return &destinationRuleSet{ + set: makeGenericDestinationRuleSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *destinationRuleSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *destinationRuleSet) Union(set DestinationRuleSet) DestinationRuleSet { if s == nil { return set } - return NewDestinationRuleSet(append(s.List(), set.List()...)...) + return NewDestinationRuleSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *destinationRuleSet) Difference(set DestinationRuleSet) DestinationRuleSet { @@ -179,7 +249,11 @@ func (s *destinationRuleSet) Difference(set DestinationRuleSet) DestinationRuleS return set } newSet := s.Generic().Difference(set.Generic()) - return &destinationRuleSet{set: newSet} + return &destinationRuleSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *destinationRuleSet) Intersection(set DestinationRuleSet) DestinationRuleSet { @@ -191,7 +265,7 @@ func (s *destinationRuleSet) Intersection(set DestinationRuleSet) DestinationRul for _, obj := range newSet.List() { destinationRuleList = append(destinationRuleList, obj.(*networking_istio_io_v1beta1.DestinationRule)) } - return NewDestinationRuleSet(destinationRuleList...) + return NewDestinationRuleSet(s.sortFunc, s.equalityFunc, destinationRuleList...) } func (s *destinationRuleSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.DestinationRule, error) { @@ -233,7 +307,63 @@ func (s *destinationRuleSet) Clone() DestinationRuleSet { if s == nil { return nil } - return &destinationRuleSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.DestinationRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &destinationRuleSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *destinationRuleSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *destinationRuleSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type GatewaySet interface { @@ -271,30 +401,98 @@ type GatewaySet interface { Delta(newSet GatewaySet) sksets.ResourceDelta // Create a deep copy of the current GatewaySet Clone() GatewaySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericGatewaySet(gatewayList []*networking_istio_io_v1beta1.Gateway) sksets.ResourceSet { +func makeGenericGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList []*networking_istio_io_v1beta1.Gateway, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range gatewayList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type gatewaySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewGatewaySet(gatewayList ...*networking_istio_io_v1beta1.Gateway) GatewaySet { - return &gatewaySet{set: makeGenericGatewaySet(gatewayList)} +func NewGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList ...*networking_istio_io_v1beta1.Gateway, +) GatewaySet { + return &gatewaySet{ + set: makeGenericGatewaySet(sortFunc, equalityFunc, gatewayList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewGatewaySetFromList(gatewayList *networking_istio_io_v1beta1.GatewayList) GatewaySet { +func NewGatewaySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList *networking_istio_io_v1beta1.GatewayList, +) GatewaySet { list := make([]*networking_istio_io_v1beta1.Gateway, 0, len(gatewayList.Items)) for idx := range gatewayList.Items { list = append(list, gatewayList.Items[idx]) } - return &gatewaySet{set: makeGenericGatewaySet(list)} + return &gatewaySet{ + set: makeGenericGatewaySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *gatewaySet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *gatewaySet) Union(set GatewaySet) GatewaySet { if s == nil { return set } - return NewGatewaySet(append(s.List(), set.List()...)...) + return NewGatewaySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *gatewaySet) Difference(set GatewaySet) GatewaySet { @@ -402,7 +600,11 @@ func (s *gatewaySet) Difference(set GatewaySet) GatewaySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &gatewaySet{set: newSet} + return &gatewaySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *gatewaySet) Intersection(set GatewaySet) GatewaySet { @@ -414,7 +616,7 @@ func (s *gatewaySet) Intersection(set GatewaySet) GatewaySet { for _, obj := range newSet.List() { gatewayList = append(gatewayList, obj.(*networking_istio_io_v1beta1.Gateway)) } - return NewGatewaySet(gatewayList...) + return NewGatewaySet(s.sortFunc, s.equalityFunc, gatewayList...) } func (s *gatewaySet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.Gateway, error) { @@ -456,7 +658,63 @@ func (s *gatewaySet) Clone() GatewaySet { if s == nil { return nil } - return &gatewaySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &gatewaySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *gatewaySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *gatewaySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ProxyConfigSet interface { @@ -494,30 +752,98 @@ type ProxyConfigSet interface { Delta(newSet ProxyConfigSet) sksets.ResourceDelta // Create a deep copy of the current ProxyConfigSet Clone() ProxyConfigSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericProxyConfigSet(proxyConfigList []*networking_istio_io_v1beta1.ProxyConfig) sksets.ResourceSet { +func makeGenericProxyConfigSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + proxyConfigList []*networking_istio_io_v1beta1.ProxyConfig, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range proxyConfigList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type proxyConfigSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewProxyConfigSet(proxyConfigList ...*networking_istio_io_v1beta1.ProxyConfig) ProxyConfigSet { - return &proxyConfigSet{set: makeGenericProxyConfigSet(proxyConfigList)} +func NewProxyConfigSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + proxyConfigList ...*networking_istio_io_v1beta1.ProxyConfig, +) ProxyConfigSet { + return &proxyConfigSet{ + set: makeGenericProxyConfigSet(sortFunc, equalityFunc, proxyConfigList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewProxyConfigSetFromList(proxyConfigList *networking_istio_io_v1beta1.ProxyConfigList) ProxyConfigSet { +func NewProxyConfigSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + proxyConfigList *networking_istio_io_v1beta1.ProxyConfigList, +) ProxyConfigSet { list := make([]*networking_istio_io_v1beta1.ProxyConfig, 0, len(proxyConfigList.Items)) for idx := range proxyConfigList.Items { list = append(list, proxyConfigList.Items[idx]) } - return &proxyConfigSet{set: makeGenericProxyConfigSet(list)} + return &proxyConfigSet{ + set: makeGenericProxyConfigSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *proxyConfigSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *proxyConfigSet) Union(set ProxyConfigSet) ProxyConfigSet { if s == nil { return set } - return NewProxyConfigSet(append(s.List(), set.List()...)...) + return NewProxyConfigSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *proxyConfigSet) Difference(set ProxyConfigSet) ProxyConfigSet { @@ -625,7 +951,11 @@ func (s *proxyConfigSet) Difference(set ProxyConfigSet) ProxyConfigSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &proxyConfigSet{set: newSet} + return &proxyConfigSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *proxyConfigSet) Intersection(set ProxyConfigSet) ProxyConfigSet { @@ -637,7 +967,7 @@ func (s *proxyConfigSet) Intersection(set ProxyConfigSet) ProxyConfigSet { for _, obj := range newSet.List() { proxyConfigList = append(proxyConfigList, obj.(*networking_istio_io_v1beta1.ProxyConfig)) } - return NewProxyConfigSet(proxyConfigList...) + return NewProxyConfigSet(s.sortFunc, s.equalityFunc, proxyConfigList...) } func (s *proxyConfigSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.ProxyConfig, error) { @@ -679,7 +1009,63 @@ func (s *proxyConfigSet) Clone() ProxyConfigSet { if s == nil { return nil } - return &proxyConfigSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.ProxyConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &proxyConfigSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *proxyConfigSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *proxyConfigSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ServiceEntrySet interface { @@ -717,30 +1103,98 @@ type ServiceEntrySet interface { Delta(newSet ServiceEntrySet) sksets.ResourceDelta // Create a deep copy of the current ServiceEntrySet Clone() ServiceEntrySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericServiceEntrySet(serviceEntryList []*networking_istio_io_v1beta1.ServiceEntry) sksets.ResourceSet { +func makeGenericServiceEntrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceEntryList []*networking_istio_io_v1beta1.ServiceEntry, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range serviceEntryList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type serviceEntrySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewServiceEntrySet(serviceEntryList ...*networking_istio_io_v1beta1.ServiceEntry) ServiceEntrySet { - return &serviceEntrySet{set: makeGenericServiceEntrySet(serviceEntryList)} +func NewServiceEntrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceEntryList ...*networking_istio_io_v1beta1.ServiceEntry, +) ServiceEntrySet { + return &serviceEntrySet{ + set: makeGenericServiceEntrySet(sortFunc, equalityFunc, serviceEntryList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewServiceEntrySetFromList(serviceEntryList *networking_istio_io_v1beta1.ServiceEntryList) ServiceEntrySet { +func NewServiceEntrySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceEntryList *networking_istio_io_v1beta1.ServiceEntryList, +) ServiceEntrySet { list := make([]*networking_istio_io_v1beta1.ServiceEntry, 0, len(serviceEntryList.Items)) for idx := range serviceEntryList.Items { list = append(list, serviceEntryList.Items[idx]) } - return &serviceEntrySet{set: makeGenericServiceEntrySet(list)} + return &serviceEntrySet{ + set: makeGenericServiceEntrySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *serviceEntrySet) Keys() sets.String { @@ -840,7 +1294,7 @@ func (s *serviceEntrySet) Union(set ServiceEntrySet) ServiceEntrySet { if s == nil { return set } - return NewServiceEntrySet(append(s.List(), set.List()...)...) + return NewServiceEntrySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *serviceEntrySet) Difference(set ServiceEntrySet) ServiceEntrySet { @@ -848,7 +1302,11 @@ func (s *serviceEntrySet) Difference(set ServiceEntrySet) ServiceEntrySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &serviceEntrySet{set: newSet} + return &serviceEntrySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *serviceEntrySet) Intersection(set ServiceEntrySet) ServiceEntrySet { @@ -860,7 +1318,7 @@ func (s *serviceEntrySet) Intersection(set ServiceEntrySet) ServiceEntrySet { for _, obj := range newSet.List() { serviceEntryList = append(serviceEntryList, obj.(*networking_istio_io_v1beta1.ServiceEntry)) } - return NewServiceEntrySet(serviceEntryList...) + return NewServiceEntrySet(s.sortFunc, s.equalityFunc, serviceEntryList...) } func (s *serviceEntrySet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.ServiceEntry, error) { @@ -902,7 +1360,63 @@ func (s *serviceEntrySet) Clone() ServiceEntrySet { if s == nil { return nil } - return &serviceEntrySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.ServiceEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &serviceEntrySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *serviceEntrySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *serviceEntrySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type WorkloadEntrySet interface { @@ -940,30 +1454,98 @@ type WorkloadEntrySet interface { Delta(newSet WorkloadEntrySet) sksets.ResourceDelta // Create a deep copy of the current WorkloadEntrySet Clone() WorkloadEntrySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericWorkloadEntrySet(workloadEntryList []*networking_istio_io_v1beta1.WorkloadEntry) sksets.ResourceSet { +func makeGenericWorkloadEntrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadEntryList []*networking_istio_io_v1beta1.WorkloadEntry, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range workloadEntryList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type workloadEntrySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewWorkloadEntrySet(workloadEntryList ...*networking_istio_io_v1beta1.WorkloadEntry) WorkloadEntrySet { - return &workloadEntrySet{set: makeGenericWorkloadEntrySet(workloadEntryList)} +func NewWorkloadEntrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadEntryList ...*networking_istio_io_v1beta1.WorkloadEntry, +) WorkloadEntrySet { + return &workloadEntrySet{ + set: makeGenericWorkloadEntrySet(sortFunc, equalityFunc, workloadEntryList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewWorkloadEntrySetFromList(workloadEntryList *networking_istio_io_v1beta1.WorkloadEntryList) WorkloadEntrySet { +func NewWorkloadEntrySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadEntryList *networking_istio_io_v1beta1.WorkloadEntryList, +) WorkloadEntrySet { list := make([]*networking_istio_io_v1beta1.WorkloadEntry, 0, len(workloadEntryList.Items)) for idx := range workloadEntryList.Items { list = append(list, workloadEntryList.Items[idx]) } - return &workloadEntrySet{set: makeGenericWorkloadEntrySet(list)} + return &workloadEntrySet{ + set: makeGenericWorkloadEntrySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *workloadEntrySet) Keys() sets.String { @@ -1063,7 +1645,7 @@ func (s *workloadEntrySet) Union(set WorkloadEntrySet) WorkloadEntrySet { if s == nil { return set } - return NewWorkloadEntrySet(append(s.List(), set.List()...)...) + return NewWorkloadEntrySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *workloadEntrySet) Difference(set WorkloadEntrySet) WorkloadEntrySet { @@ -1071,7 +1653,11 @@ func (s *workloadEntrySet) Difference(set WorkloadEntrySet) WorkloadEntrySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &workloadEntrySet{set: newSet} + return &workloadEntrySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *workloadEntrySet) Intersection(set WorkloadEntrySet) WorkloadEntrySet { @@ -1083,7 +1669,7 @@ func (s *workloadEntrySet) Intersection(set WorkloadEntrySet) WorkloadEntrySet { for _, obj := range newSet.List() { workloadEntryList = append(workloadEntryList, obj.(*networking_istio_io_v1beta1.WorkloadEntry)) } - return NewWorkloadEntrySet(workloadEntryList...) + return NewWorkloadEntrySet(s.sortFunc, s.equalityFunc, workloadEntryList...) } func (s *workloadEntrySet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.WorkloadEntry, error) { @@ -1125,7 +1711,63 @@ func (s *workloadEntrySet) Clone() WorkloadEntrySet { if s == nil { return nil } - return &workloadEntrySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.WorkloadEntry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &workloadEntrySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *workloadEntrySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *workloadEntrySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type WorkloadGroupSet interface { @@ -1163,30 +1805,98 @@ type WorkloadGroupSet interface { Delta(newSet WorkloadGroupSet) sksets.ResourceDelta // Create a deep copy of the current WorkloadGroupSet Clone() WorkloadGroupSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericWorkloadGroupSet(workloadGroupList []*networking_istio_io_v1beta1.WorkloadGroup) sksets.ResourceSet { +func makeGenericWorkloadGroupSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadGroupList []*networking_istio_io_v1beta1.WorkloadGroup, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range workloadGroupList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type workloadGroupSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewWorkloadGroupSet(workloadGroupList ...*networking_istio_io_v1beta1.WorkloadGroup) WorkloadGroupSet { - return &workloadGroupSet{set: makeGenericWorkloadGroupSet(workloadGroupList)} +func NewWorkloadGroupSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadGroupList ...*networking_istio_io_v1beta1.WorkloadGroup, +) WorkloadGroupSet { + return &workloadGroupSet{ + set: makeGenericWorkloadGroupSet(sortFunc, equalityFunc, workloadGroupList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewWorkloadGroupSetFromList(workloadGroupList *networking_istio_io_v1beta1.WorkloadGroupList) WorkloadGroupSet { +func NewWorkloadGroupSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + workloadGroupList *networking_istio_io_v1beta1.WorkloadGroupList, +) WorkloadGroupSet { list := make([]*networking_istio_io_v1beta1.WorkloadGroup, 0, len(workloadGroupList.Items)) for idx := range workloadGroupList.Items { list = append(list, workloadGroupList.Items[idx]) } - return &workloadGroupSet{set: makeGenericWorkloadGroupSet(list)} + return &workloadGroupSet{ + set: makeGenericWorkloadGroupSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *workloadGroupSet) Keys() sets.String { @@ -1286,7 +1996,7 @@ func (s *workloadGroupSet) Union(set WorkloadGroupSet) WorkloadGroupSet { if s == nil { return set } - return NewWorkloadGroupSet(append(s.List(), set.List()...)...) + return NewWorkloadGroupSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *workloadGroupSet) Difference(set WorkloadGroupSet) WorkloadGroupSet { @@ -1294,7 +2004,11 @@ func (s *workloadGroupSet) Difference(set WorkloadGroupSet) WorkloadGroupSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &workloadGroupSet{set: newSet} + return &workloadGroupSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *workloadGroupSet) Intersection(set WorkloadGroupSet) WorkloadGroupSet { @@ -1306,7 +2020,7 @@ func (s *workloadGroupSet) Intersection(set WorkloadGroupSet) WorkloadGroupSet { for _, obj := range newSet.List() { workloadGroupList = append(workloadGroupList, obj.(*networking_istio_io_v1beta1.WorkloadGroup)) } - return NewWorkloadGroupSet(workloadGroupList...) + return NewWorkloadGroupSet(s.sortFunc, s.equalityFunc, workloadGroupList...) } func (s *workloadGroupSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.WorkloadGroup, error) { @@ -1348,7 +2062,63 @@ func (s *workloadGroupSet) Clone() WorkloadGroupSet { if s == nil { return nil } - return &workloadGroupSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.WorkloadGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &workloadGroupSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *workloadGroupSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *workloadGroupSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type VirtualServiceSet interface { @@ -1386,30 +2156,98 @@ type VirtualServiceSet interface { Delta(newSet VirtualServiceSet) sksets.ResourceDelta // Create a deep copy of the current VirtualServiceSet Clone() VirtualServiceSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericVirtualServiceSet(virtualServiceList []*networking_istio_io_v1beta1.VirtualService) sksets.ResourceSet { +func makeGenericVirtualServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList []*networking_istio_io_v1beta1.VirtualService, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range virtualServiceList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type virtualServiceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewVirtualServiceSet(virtualServiceList ...*networking_istio_io_v1beta1.VirtualService) VirtualServiceSet { - return &virtualServiceSet{set: makeGenericVirtualServiceSet(virtualServiceList)} +func NewVirtualServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList ...*networking_istio_io_v1beta1.VirtualService, +) VirtualServiceSet { + return &virtualServiceSet{ + set: makeGenericVirtualServiceSet(sortFunc, equalityFunc, virtualServiceList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewVirtualServiceSetFromList(virtualServiceList *networking_istio_io_v1beta1.VirtualServiceList) VirtualServiceSet { +func NewVirtualServiceSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + virtualServiceList *networking_istio_io_v1beta1.VirtualServiceList, +) VirtualServiceSet { list := make([]*networking_istio_io_v1beta1.VirtualService, 0, len(virtualServiceList.Items)) for idx := range virtualServiceList.Items { list = append(list, virtualServiceList.Items[idx]) } - return &virtualServiceSet{set: makeGenericVirtualServiceSet(list)} + return &virtualServiceSet{ + set: makeGenericVirtualServiceSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *virtualServiceSet) Keys() sets.String { @@ -1509,7 +2347,7 @@ func (s *virtualServiceSet) Union(set VirtualServiceSet) VirtualServiceSet { if s == nil { return set } - return NewVirtualServiceSet(append(s.List(), set.List()...)...) + return NewVirtualServiceSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *virtualServiceSet) Difference(set VirtualServiceSet) VirtualServiceSet { @@ -1517,7 +2355,11 @@ func (s *virtualServiceSet) Difference(set VirtualServiceSet) VirtualServiceSet return set } newSet := s.Generic().Difference(set.Generic()) - return &virtualServiceSet{set: newSet} + return &virtualServiceSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *virtualServiceSet) Intersection(set VirtualServiceSet) VirtualServiceSet { @@ -1529,7 +2371,7 @@ func (s *virtualServiceSet) Intersection(set VirtualServiceSet) VirtualServiceSe for _, obj := range newSet.List() { virtualServiceList = append(virtualServiceList, obj.(*networking_istio_io_v1beta1.VirtualService)) } - return NewVirtualServiceSet(virtualServiceList...) + return NewVirtualServiceSet(s.sortFunc, s.equalityFunc, virtualServiceList...) } func (s *virtualServiceSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.VirtualService, error) { @@ -1571,7 +2413,63 @@ func (s *virtualServiceSet) Clone() VirtualServiceSet { if s == nil { return nil } - return &virtualServiceSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.VirtualService{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &virtualServiceSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *virtualServiceSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *virtualServiceSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type SidecarSet interface { @@ -1609,30 +2507,98 @@ type SidecarSet interface { Delta(newSet SidecarSet) sksets.ResourceDelta // Create a deep copy of the current SidecarSet Clone() SidecarSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericSidecarSet(sidecarList []*networking_istio_io_v1beta1.Sidecar) sksets.ResourceSet { +func makeGenericSidecarSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + sidecarList []*networking_istio_io_v1beta1.Sidecar, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range sidecarList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type sidecarSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewSidecarSet(sidecarList ...*networking_istio_io_v1beta1.Sidecar) SidecarSet { - return &sidecarSet{set: makeGenericSidecarSet(sidecarList)} +func NewSidecarSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + sidecarList ...*networking_istio_io_v1beta1.Sidecar, +) SidecarSet { + return &sidecarSet{ + set: makeGenericSidecarSet(sortFunc, equalityFunc, sidecarList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewSidecarSetFromList(sidecarList *networking_istio_io_v1beta1.SidecarList) SidecarSet { +func NewSidecarSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + sidecarList *networking_istio_io_v1beta1.SidecarList, +) SidecarSet { list := make([]*networking_istio_io_v1beta1.Sidecar, 0, len(sidecarList.Items)) for idx := range sidecarList.Items { list = append(list, sidecarList.Items[idx]) } - return &sidecarSet{set: makeGenericSidecarSet(list)} + return &sidecarSet{ + set: makeGenericSidecarSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *sidecarSet) Keys() sets.String { @@ -1732,7 +2698,7 @@ func (s *sidecarSet) Union(set SidecarSet) SidecarSet { if s == nil { return set } - return NewSidecarSet(append(s.List(), set.List()...)...) + return NewSidecarSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *sidecarSet) Difference(set SidecarSet) SidecarSet { @@ -1740,7 +2706,11 @@ func (s *sidecarSet) Difference(set SidecarSet) SidecarSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &sidecarSet{set: newSet} + return &sidecarSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *sidecarSet) Intersection(set SidecarSet) SidecarSet { @@ -1752,7 +2722,7 @@ func (s *sidecarSet) Intersection(set SidecarSet) SidecarSet { for _, obj := range newSet.List() { sidecarList = append(sidecarList, obj.(*networking_istio_io_v1beta1.Sidecar)) } - return NewSidecarSet(sidecarList...) + return NewSidecarSet(s.sortFunc, s.equalityFunc, sidecarList...) } func (s *sidecarSet) Find(id ezkube.ResourceId) (*networking_istio_io_v1beta1.Sidecar, error) { @@ -1794,5 +2764,61 @@ func (s *sidecarSet) Clone() SidecarSet { if s == nil { return nil } - return &sidecarSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_istio_io_v1beta1.Sidecar{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &sidecarSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *sidecarSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *sidecarSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/security.istio.io/v1beta1/sets/mocks/sets.go b/pkg/api/istio/security.istio.io/v1beta1/sets/mocks/sets.go index 8e4b465..5597db1 100644 --- a/pkg/api/istio/security.istio.io/v1beta1/sets/mocks/sets.go +++ b/pkg/api/istio/security.istio.io/v1beta1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1beta1 "istio.io/client-go/pkg/apis/security/v1beta1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockAuthorizationPolicySet is a mock of AuthorizationPolicySet interface. @@ -135,6 +136,34 @@ func (mr *MockAuthorizationPolicySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockAuthorizationPolicySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockAuthorizationPolicySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockAuthorizationPolicySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockAuthorizationPolicySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockAuthorizationPolicySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockAuthorizationPolicySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockAuthorizationPolicySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockAuthorizationPolicySet) Has(authorizationPolicy ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockPeerAuthenticationSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockPeerAuthenticationSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockPeerAuthenticationSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockPeerAuthenticationSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockPeerAuthenticationSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockPeerAuthenticationSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockPeerAuthenticationSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockPeerAuthenticationSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockPeerAuthenticationSet) Has(peerAuthentication ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockRequestAuthenticationSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockRequestAuthenticationSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockRequestAuthenticationSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockRequestAuthenticationSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockRequestAuthenticationSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockRequestAuthenticationSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockRequestAuthenticationSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockRequestAuthenticationSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockRequestAuthenticationSet) Has(requestAuthentication ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/security.istio.io/v1beta1/sets/sets.go b/pkg/api/istio/security.istio.io/v1beta1/sets/sets.go index 0e67b25..9ca8994 100644 --- a/pkg/api/istio/security.istio.io/v1beta1/sets/sets.go +++ b/pkg/api/istio/security.istio.io/v1beta1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type AuthorizationPolicySet interface { @@ -48,30 +50,98 @@ type AuthorizationPolicySet interface { Delta(newSet AuthorizationPolicySet) sksets.ResourceDelta // Create a deep copy of the current AuthorizationPolicySet Clone() AuthorizationPolicySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericAuthorizationPolicySet(authorizationPolicyList []*security_istio_io_v1beta1.AuthorizationPolicy) sksets.ResourceSet { +func makeGenericAuthorizationPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + authorizationPolicyList []*security_istio_io_v1beta1.AuthorizationPolicy, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range authorizationPolicyList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type authorizationPolicySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewAuthorizationPolicySet(authorizationPolicyList ...*security_istio_io_v1beta1.AuthorizationPolicy) AuthorizationPolicySet { - return &authorizationPolicySet{set: makeGenericAuthorizationPolicySet(authorizationPolicyList)} +func NewAuthorizationPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + authorizationPolicyList ...*security_istio_io_v1beta1.AuthorizationPolicy, +) AuthorizationPolicySet { + return &authorizationPolicySet{ + set: makeGenericAuthorizationPolicySet(sortFunc, equalityFunc, authorizationPolicyList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewAuthorizationPolicySetFromList(authorizationPolicyList *security_istio_io_v1beta1.AuthorizationPolicyList) AuthorizationPolicySet { +func NewAuthorizationPolicySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + authorizationPolicyList *security_istio_io_v1beta1.AuthorizationPolicyList, +) AuthorizationPolicySet { list := make([]*security_istio_io_v1beta1.AuthorizationPolicy, 0, len(authorizationPolicyList.Items)) for idx := range authorizationPolicyList.Items { list = append(list, authorizationPolicyList.Items[idx]) } - return &authorizationPolicySet{set: makeGenericAuthorizationPolicySet(list)} + return &authorizationPolicySet{ + set: makeGenericAuthorizationPolicySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *authorizationPolicySet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *authorizationPolicySet) Union(set AuthorizationPolicySet) Authorization if s == nil { return set } - return NewAuthorizationPolicySet(append(s.List(), set.List()...)...) + return NewAuthorizationPolicySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *authorizationPolicySet) Difference(set AuthorizationPolicySet) AuthorizationPolicySet { @@ -179,7 +249,11 @@ func (s *authorizationPolicySet) Difference(set AuthorizationPolicySet) Authoriz return set } newSet := s.Generic().Difference(set.Generic()) - return &authorizationPolicySet{set: newSet} + return &authorizationPolicySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *authorizationPolicySet) Intersection(set AuthorizationPolicySet) AuthorizationPolicySet { @@ -191,7 +265,7 @@ func (s *authorizationPolicySet) Intersection(set AuthorizationPolicySet) Author for _, obj := range newSet.List() { authorizationPolicyList = append(authorizationPolicyList, obj.(*security_istio_io_v1beta1.AuthorizationPolicy)) } - return NewAuthorizationPolicySet(authorizationPolicyList...) + return NewAuthorizationPolicySet(s.sortFunc, s.equalityFunc, authorizationPolicyList...) } func (s *authorizationPolicySet) Find(id ezkube.ResourceId) (*security_istio_io_v1beta1.AuthorizationPolicy, error) { @@ -233,7 +307,63 @@ func (s *authorizationPolicySet) Clone() AuthorizationPolicySet { if s == nil { return nil } - return &authorizationPolicySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.AuthorizationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &authorizationPolicySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *authorizationPolicySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *authorizationPolicySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type PeerAuthenticationSet interface { @@ -271,30 +401,98 @@ type PeerAuthenticationSet interface { Delta(newSet PeerAuthenticationSet) sksets.ResourceDelta // Create a deep copy of the current PeerAuthenticationSet Clone() PeerAuthenticationSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericPeerAuthenticationSet(peerAuthenticationList []*security_istio_io_v1beta1.PeerAuthentication) sksets.ResourceSet { +func makeGenericPeerAuthenticationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + peerAuthenticationList []*security_istio_io_v1beta1.PeerAuthentication, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range peerAuthenticationList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type peerAuthenticationSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewPeerAuthenticationSet(peerAuthenticationList ...*security_istio_io_v1beta1.PeerAuthentication) PeerAuthenticationSet { - return &peerAuthenticationSet{set: makeGenericPeerAuthenticationSet(peerAuthenticationList)} +func NewPeerAuthenticationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + peerAuthenticationList ...*security_istio_io_v1beta1.PeerAuthentication, +) PeerAuthenticationSet { + return &peerAuthenticationSet{ + set: makeGenericPeerAuthenticationSet(sortFunc, equalityFunc, peerAuthenticationList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewPeerAuthenticationSetFromList(peerAuthenticationList *security_istio_io_v1beta1.PeerAuthenticationList) PeerAuthenticationSet { +func NewPeerAuthenticationSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + peerAuthenticationList *security_istio_io_v1beta1.PeerAuthenticationList, +) PeerAuthenticationSet { list := make([]*security_istio_io_v1beta1.PeerAuthentication, 0, len(peerAuthenticationList.Items)) for idx := range peerAuthenticationList.Items { list = append(list, peerAuthenticationList.Items[idx]) } - return &peerAuthenticationSet{set: makeGenericPeerAuthenticationSet(list)} + return &peerAuthenticationSet{ + set: makeGenericPeerAuthenticationSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *peerAuthenticationSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *peerAuthenticationSet) Union(set PeerAuthenticationSet) PeerAuthenticat if s == nil { return set } - return NewPeerAuthenticationSet(append(s.List(), set.List()...)...) + return NewPeerAuthenticationSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *peerAuthenticationSet) Difference(set PeerAuthenticationSet) PeerAuthenticationSet { @@ -402,7 +600,11 @@ func (s *peerAuthenticationSet) Difference(set PeerAuthenticationSet) PeerAuthen return set } newSet := s.Generic().Difference(set.Generic()) - return &peerAuthenticationSet{set: newSet} + return &peerAuthenticationSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *peerAuthenticationSet) Intersection(set PeerAuthenticationSet) PeerAuthenticationSet { @@ -414,7 +616,7 @@ func (s *peerAuthenticationSet) Intersection(set PeerAuthenticationSet) PeerAuth for _, obj := range newSet.List() { peerAuthenticationList = append(peerAuthenticationList, obj.(*security_istio_io_v1beta1.PeerAuthentication)) } - return NewPeerAuthenticationSet(peerAuthenticationList...) + return NewPeerAuthenticationSet(s.sortFunc, s.equalityFunc, peerAuthenticationList...) } func (s *peerAuthenticationSet) Find(id ezkube.ResourceId) (*security_istio_io_v1beta1.PeerAuthentication, error) { @@ -456,7 +658,63 @@ func (s *peerAuthenticationSet) Clone() PeerAuthenticationSet { if s == nil { return nil } - return &peerAuthenticationSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.PeerAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &peerAuthenticationSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *peerAuthenticationSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *peerAuthenticationSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type RequestAuthenticationSet interface { @@ -494,30 +752,98 @@ type RequestAuthenticationSet interface { Delta(newSet RequestAuthenticationSet) sksets.ResourceDelta // Create a deep copy of the current RequestAuthenticationSet Clone() RequestAuthenticationSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericRequestAuthenticationSet(requestAuthenticationList []*security_istio_io_v1beta1.RequestAuthentication) sksets.ResourceSet { +func makeGenericRequestAuthenticationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + requestAuthenticationList []*security_istio_io_v1beta1.RequestAuthentication, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range requestAuthenticationList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type requestAuthenticationSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewRequestAuthenticationSet(requestAuthenticationList ...*security_istio_io_v1beta1.RequestAuthentication) RequestAuthenticationSet { - return &requestAuthenticationSet{set: makeGenericRequestAuthenticationSet(requestAuthenticationList)} +func NewRequestAuthenticationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + requestAuthenticationList ...*security_istio_io_v1beta1.RequestAuthentication, +) RequestAuthenticationSet { + return &requestAuthenticationSet{ + set: makeGenericRequestAuthenticationSet(sortFunc, equalityFunc, requestAuthenticationList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewRequestAuthenticationSetFromList(requestAuthenticationList *security_istio_io_v1beta1.RequestAuthenticationList) RequestAuthenticationSet { +func NewRequestAuthenticationSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + requestAuthenticationList *security_istio_io_v1beta1.RequestAuthenticationList, +) RequestAuthenticationSet { list := make([]*security_istio_io_v1beta1.RequestAuthentication, 0, len(requestAuthenticationList.Items)) for idx := range requestAuthenticationList.Items { list = append(list, requestAuthenticationList.Items[idx]) } - return &requestAuthenticationSet{set: makeGenericRequestAuthenticationSet(list)} + return &requestAuthenticationSet{ + set: makeGenericRequestAuthenticationSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *requestAuthenticationSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *requestAuthenticationSet) Union(set RequestAuthenticationSet) RequestAu if s == nil { return set } - return NewRequestAuthenticationSet(append(s.List(), set.List()...)...) + return NewRequestAuthenticationSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *requestAuthenticationSet) Difference(set RequestAuthenticationSet) RequestAuthenticationSet { @@ -625,7 +951,11 @@ func (s *requestAuthenticationSet) Difference(set RequestAuthenticationSet) Requ return set } newSet := s.Generic().Difference(set.Generic()) - return &requestAuthenticationSet{set: newSet} + return &requestAuthenticationSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *requestAuthenticationSet) Intersection(set RequestAuthenticationSet) RequestAuthenticationSet { @@ -637,7 +967,7 @@ func (s *requestAuthenticationSet) Intersection(set RequestAuthenticationSet) Re for _, obj := range newSet.List() { requestAuthenticationList = append(requestAuthenticationList, obj.(*security_istio_io_v1beta1.RequestAuthentication)) } - return NewRequestAuthenticationSet(requestAuthenticationList...) + return NewRequestAuthenticationSet(s.sortFunc, s.equalityFunc, requestAuthenticationList...) } func (s *requestAuthenticationSet) Find(id ezkube.ResourceId) (*security_istio_io_v1beta1.RequestAuthentication, error) { @@ -679,5 +1009,61 @@ func (s *requestAuthenticationSet) Clone() RequestAuthenticationSet { if s == nil { return nil } - return &requestAuthenticationSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &security_istio_io_v1beta1.RequestAuthentication{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &requestAuthenticationSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *requestAuthenticationSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *requestAuthenticationSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/mocks/sets.go b/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/mocks/sets.go index de0034d..346b005 100644 --- a/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/mocks/sets.go +++ b/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1alpha1 "istio.io/client-go/pkg/apis/telemetry/v1alpha1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockTelemetrySet is a mock of TelemetrySet interface. @@ -135,6 +136,34 @@ func (mr *MockTelemetrySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockTelemetrySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockTelemetrySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockTelemetrySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockTelemetrySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockTelemetrySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockTelemetrySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockTelemetrySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockTelemetrySet) Has(telemetry ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/sets.go b/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/sets.go index 48968b4..c9f7939 100644 --- a/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/sets.go +++ b/pkg/api/istio/telemetry.istio.io/v1alpha1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type TelemetrySet interface { @@ -48,30 +50,98 @@ type TelemetrySet interface { Delta(newSet TelemetrySet) sksets.ResourceDelta // Create a deep copy of the current TelemetrySet Clone() TelemetrySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericTelemetrySet(telemetryList []*telemetry_istio_io_v1alpha1.Telemetry) sksets.ResourceSet { +func makeGenericTelemetrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + telemetryList []*telemetry_istio_io_v1alpha1.Telemetry, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range telemetryList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type telemetrySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewTelemetrySet(telemetryList ...*telemetry_istio_io_v1alpha1.Telemetry) TelemetrySet { - return &telemetrySet{set: makeGenericTelemetrySet(telemetryList)} +func NewTelemetrySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + telemetryList ...*telemetry_istio_io_v1alpha1.Telemetry, +) TelemetrySet { + return &telemetrySet{ + set: makeGenericTelemetrySet(sortFunc, equalityFunc, telemetryList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewTelemetrySetFromList(telemetryList *telemetry_istio_io_v1alpha1.TelemetryList) TelemetrySet { +func NewTelemetrySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + telemetryList *telemetry_istio_io_v1alpha1.TelemetryList, +) TelemetrySet { list := make([]*telemetry_istio_io_v1alpha1.Telemetry, 0, len(telemetryList.Items)) for idx := range telemetryList.Items { list = append(list, telemetryList.Items[idx]) } - return &telemetrySet{set: makeGenericTelemetrySet(list)} + return &telemetrySet{ + set: makeGenericTelemetrySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *telemetrySet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *telemetrySet) Union(set TelemetrySet) TelemetrySet { if s == nil { return set } - return NewTelemetrySet(append(s.List(), set.List()...)...) + return NewTelemetrySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *telemetrySet) Difference(set TelemetrySet) TelemetrySet { @@ -179,7 +249,11 @@ func (s *telemetrySet) Difference(set TelemetrySet) TelemetrySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &telemetrySet{set: newSet} + return &telemetrySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *telemetrySet) Intersection(set TelemetrySet) TelemetrySet { @@ -191,7 +265,7 @@ func (s *telemetrySet) Intersection(set TelemetrySet) TelemetrySet { for _, obj := range newSet.List() { telemetryList = append(telemetryList, obj.(*telemetry_istio_io_v1alpha1.Telemetry)) } - return NewTelemetrySet(telemetryList...) + return NewTelemetrySet(s.sortFunc, s.equalityFunc, telemetryList...) } func (s *telemetrySet) Find(id ezkube.ResourceId) (*telemetry_istio_io_v1alpha1.Telemetry, error) { @@ -233,5 +307,61 @@ func (s *telemetrySet) Clone() TelemetrySet { if s == nil { return nil } - return &telemetrySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &telemetry_istio_io_v1alpha1.Telemetry{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &telemetrySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *telemetrySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *telemetrySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/mocks/sets.go b/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/mocks/sets.go index ded7a36..e5b4745 100644 --- a/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/admissionregistration/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockValidatingWebhookConfigurationSet is a mock of ValidatingWebhookConfigurationSet interface. @@ -135,6 +136,34 @@ func (mr *MockValidatingWebhookConfigurationSetMockRecorder) Generic() *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockValidatingWebhookConfigurationSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockValidatingWebhookConfigurationSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockValidatingWebhookConfigurationSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockValidatingWebhookConfigurationSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockValidatingWebhookConfigurationSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockValidatingWebhookConfigurationSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockValidatingWebhookConfigurationSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockValidatingWebhookConfigurationSet) Has(validatingWebhookConfiguration ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockMutatingWebhookConfigurationSetMockRecorder) Generic() *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockMutatingWebhookConfigurationSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockMutatingWebhookConfigurationSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockMutatingWebhookConfigurationSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockMutatingWebhookConfigurationSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockMutatingWebhookConfigurationSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockMutatingWebhookConfigurationSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockMutatingWebhookConfigurationSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockMutatingWebhookConfigurationSet) Has(mutatingWebhookConfiguration ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/sets.go b/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/sets.go index ac493b6..5f7533c 100644 --- a/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/sets.go +++ b/pkg/api/k8s/admissionregistration.k8s.io/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type ValidatingWebhookConfigurationSet interface { @@ -48,30 +50,98 @@ type ValidatingWebhookConfigurationSet interface { Delta(newSet ValidatingWebhookConfigurationSet) sksets.ResourceDelta // Create a deep copy of the current ValidatingWebhookConfigurationSet Clone() ValidatingWebhookConfigurationSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericValidatingWebhookConfigurationSet(validatingWebhookConfigurationList []*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration) sksets.ResourceSet { +func makeGenericValidatingWebhookConfigurationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + validatingWebhookConfigurationList []*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range validatingWebhookConfigurationList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type validatingWebhookConfigurationSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewValidatingWebhookConfigurationSet(validatingWebhookConfigurationList ...*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration) ValidatingWebhookConfigurationSet { - return &validatingWebhookConfigurationSet{set: makeGenericValidatingWebhookConfigurationSet(validatingWebhookConfigurationList)} +func NewValidatingWebhookConfigurationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + validatingWebhookConfigurationList ...*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration, +) ValidatingWebhookConfigurationSet { + return &validatingWebhookConfigurationSet{ + set: makeGenericValidatingWebhookConfigurationSet(sortFunc, equalityFunc, validatingWebhookConfigurationList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewValidatingWebhookConfigurationSetFromList(validatingWebhookConfigurationList *admissionregistration_k8s_io_v1.ValidatingWebhookConfigurationList) ValidatingWebhookConfigurationSet { +func NewValidatingWebhookConfigurationSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + validatingWebhookConfigurationList *admissionregistration_k8s_io_v1.ValidatingWebhookConfigurationList, +) ValidatingWebhookConfigurationSet { list := make([]*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration, 0, len(validatingWebhookConfigurationList.Items)) for idx := range validatingWebhookConfigurationList.Items { list = append(list, &validatingWebhookConfigurationList.Items[idx]) } - return &validatingWebhookConfigurationSet{set: makeGenericValidatingWebhookConfigurationSet(list)} + return &validatingWebhookConfigurationSet{ + set: makeGenericValidatingWebhookConfigurationSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *validatingWebhookConfigurationSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *validatingWebhookConfigurationSet) Union(set ValidatingWebhookConfigura if s == nil { return set } - return NewValidatingWebhookConfigurationSet(append(s.List(), set.List()...)...) + return NewValidatingWebhookConfigurationSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *validatingWebhookConfigurationSet) Difference(set ValidatingWebhookConfigurationSet) ValidatingWebhookConfigurationSet { @@ -179,7 +249,11 @@ func (s *validatingWebhookConfigurationSet) Difference(set ValidatingWebhookConf return set } newSet := s.Generic().Difference(set.Generic()) - return &validatingWebhookConfigurationSet{set: newSet} + return &validatingWebhookConfigurationSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *validatingWebhookConfigurationSet) Intersection(set ValidatingWebhookConfigurationSet) ValidatingWebhookConfigurationSet { @@ -191,7 +265,7 @@ func (s *validatingWebhookConfigurationSet) Intersection(set ValidatingWebhookCo for _, obj := range newSet.List() { validatingWebhookConfigurationList = append(validatingWebhookConfigurationList, obj.(*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration)) } - return NewValidatingWebhookConfigurationSet(validatingWebhookConfigurationList...) + return NewValidatingWebhookConfigurationSet(s.sortFunc, s.equalityFunc, validatingWebhookConfigurationList...) } func (s *validatingWebhookConfigurationSet) Find(id ezkube.ResourceId) (*admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration, error) { @@ -233,7 +307,63 @@ func (s *validatingWebhookConfigurationSet) Clone() ValidatingWebhookConfigurati if s == nil { return nil } - return &validatingWebhookConfigurationSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &admissionregistration_k8s_io_v1.ValidatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &validatingWebhookConfigurationSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *validatingWebhookConfigurationSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *validatingWebhookConfigurationSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type MutatingWebhookConfigurationSet interface { @@ -271,30 +401,98 @@ type MutatingWebhookConfigurationSet interface { Delta(newSet MutatingWebhookConfigurationSet) sksets.ResourceDelta // Create a deep copy of the current MutatingWebhookConfigurationSet Clone() MutatingWebhookConfigurationSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericMutatingWebhookConfigurationSet(mutatingWebhookConfigurationList []*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration) sksets.ResourceSet { +func makeGenericMutatingWebhookConfigurationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + mutatingWebhookConfigurationList []*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range mutatingWebhookConfigurationList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type mutatingWebhookConfigurationSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewMutatingWebhookConfigurationSet(mutatingWebhookConfigurationList ...*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration) MutatingWebhookConfigurationSet { - return &mutatingWebhookConfigurationSet{set: makeGenericMutatingWebhookConfigurationSet(mutatingWebhookConfigurationList)} +func NewMutatingWebhookConfigurationSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + mutatingWebhookConfigurationList ...*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration, +) MutatingWebhookConfigurationSet { + return &mutatingWebhookConfigurationSet{ + set: makeGenericMutatingWebhookConfigurationSet(sortFunc, equalityFunc, mutatingWebhookConfigurationList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewMutatingWebhookConfigurationSetFromList(mutatingWebhookConfigurationList *admissionregistration_k8s_io_v1.MutatingWebhookConfigurationList) MutatingWebhookConfigurationSet { +func NewMutatingWebhookConfigurationSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + mutatingWebhookConfigurationList *admissionregistration_k8s_io_v1.MutatingWebhookConfigurationList, +) MutatingWebhookConfigurationSet { list := make([]*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration, 0, len(mutatingWebhookConfigurationList.Items)) for idx := range mutatingWebhookConfigurationList.Items { list = append(list, &mutatingWebhookConfigurationList.Items[idx]) } - return &mutatingWebhookConfigurationSet{set: makeGenericMutatingWebhookConfigurationSet(list)} + return &mutatingWebhookConfigurationSet{ + set: makeGenericMutatingWebhookConfigurationSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *mutatingWebhookConfigurationSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *mutatingWebhookConfigurationSet) Union(set MutatingWebhookConfiguration if s == nil { return set } - return NewMutatingWebhookConfigurationSet(append(s.List(), set.List()...)...) + return NewMutatingWebhookConfigurationSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *mutatingWebhookConfigurationSet) Difference(set MutatingWebhookConfigurationSet) MutatingWebhookConfigurationSet { @@ -402,7 +600,11 @@ func (s *mutatingWebhookConfigurationSet) Difference(set MutatingWebhookConfigur return set } newSet := s.Generic().Difference(set.Generic()) - return &mutatingWebhookConfigurationSet{set: newSet} + return &mutatingWebhookConfigurationSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *mutatingWebhookConfigurationSet) Intersection(set MutatingWebhookConfigurationSet) MutatingWebhookConfigurationSet { @@ -414,7 +616,7 @@ func (s *mutatingWebhookConfigurationSet) Intersection(set MutatingWebhookConfig for _, obj := range newSet.List() { mutatingWebhookConfigurationList = append(mutatingWebhookConfigurationList, obj.(*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration)) } - return NewMutatingWebhookConfigurationSet(mutatingWebhookConfigurationList...) + return NewMutatingWebhookConfigurationSet(s.sortFunc, s.equalityFunc, mutatingWebhookConfigurationList...) } func (s *mutatingWebhookConfigurationSet) Find(id ezkube.ResourceId) (*admissionregistration_k8s_io_v1.MutatingWebhookConfiguration, error) { @@ -456,5 +658,61 @@ func (s *mutatingWebhookConfigurationSet) Clone() MutatingWebhookConfigurationSe if s == nil { return nil } - return &mutatingWebhookConfigurationSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &admissionregistration_k8s_io_v1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &mutatingWebhookConfigurationSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *mutatingWebhookConfigurationSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *mutatingWebhookConfigurationSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/apiextensions.k8s.io/v1/sets/mocks/sets.go b/pkg/api/k8s/apiextensions.k8s.io/v1/sets/mocks/sets.go index d3b9287..5189ebf 100644 --- a/pkg/api/k8s/apiextensions.k8s.io/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/apiextensions.k8s.io/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockCustomResourceDefinitionSet is a mock of CustomResourceDefinitionSet interface. @@ -135,6 +136,34 @@ func (mr *MockCustomResourceDefinitionSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockCustomResourceDefinitionSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockCustomResourceDefinitionSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockCustomResourceDefinitionSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockCustomResourceDefinitionSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockCustomResourceDefinitionSet) Has(customResourceDefinition ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/apiextensions.k8s.io/v1/sets/sets.go b/pkg/api/k8s/apiextensions.k8s.io/v1/sets/sets.go index 714a4d8..2c955d1 100644 --- a/pkg/api/k8s/apiextensions.k8s.io/v1/sets/sets.go +++ b/pkg/api/k8s/apiextensions.k8s.io/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type CustomResourceDefinitionSet interface { @@ -48,30 +50,98 @@ type CustomResourceDefinitionSet interface { Delta(newSet CustomResourceDefinitionSet) sksets.ResourceDelta // Create a deep copy of the current CustomResourceDefinitionSet Clone() CustomResourceDefinitionSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericCustomResourceDefinitionSet(customResourceDefinitionList []*apiextensions_k8s_io_v1.CustomResourceDefinition) sksets.ResourceSet { +func makeGenericCustomResourceDefinitionSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList []*apiextensions_k8s_io_v1.CustomResourceDefinition, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range customResourceDefinitionList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type customResourceDefinitionSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewCustomResourceDefinitionSet(customResourceDefinitionList ...*apiextensions_k8s_io_v1.CustomResourceDefinition) CustomResourceDefinitionSet { - return &customResourceDefinitionSet{set: makeGenericCustomResourceDefinitionSet(customResourceDefinitionList)} +func NewCustomResourceDefinitionSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList ...*apiextensions_k8s_io_v1.CustomResourceDefinition, +) CustomResourceDefinitionSet { + return &customResourceDefinitionSet{ + set: makeGenericCustomResourceDefinitionSet(sortFunc, equalityFunc, customResourceDefinitionList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewCustomResourceDefinitionSetFromList(customResourceDefinitionList *apiextensions_k8s_io_v1.CustomResourceDefinitionList) CustomResourceDefinitionSet { +func NewCustomResourceDefinitionSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList *apiextensions_k8s_io_v1.CustomResourceDefinitionList, +) CustomResourceDefinitionSet { list := make([]*apiextensions_k8s_io_v1.CustomResourceDefinition, 0, len(customResourceDefinitionList.Items)) for idx := range customResourceDefinitionList.Items { list = append(list, &customResourceDefinitionList.Items[idx]) } - return &customResourceDefinitionSet{set: makeGenericCustomResourceDefinitionSet(list)} + return &customResourceDefinitionSet{ + set: makeGenericCustomResourceDefinitionSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *customResourceDefinitionSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *customResourceDefinitionSet) Union(set CustomResourceDefinitionSet) Cus if s == nil { return set } - return NewCustomResourceDefinitionSet(append(s.List(), set.List()...)...) + return NewCustomResourceDefinitionSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *customResourceDefinitionSet) Difference(set CustomResourceDefinitionSet) CustomResourceDefinitionSet { @@ -179,7 +249,11 @@ func (s *customResourceDefinitionSet) Difference(set CustomResourceDefinitionSet return set } newSet := s.Generic().Difference(set.Generic()) - return &customResourceDefinitionSet{set: newSet} + return &customResourceDefinitionSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *customResourceDefinitionSet) Intersection(set CustomResourceDefinitionSet) CustomResourceDefinitionSet { @@ -191,7 +265,7 @@ func (s *customResourceDefinitionSet) Intersection(set CustomResourceDefinitionS for _, obj := range newSet.List() { customResourceDefinitionList = append(customResourceDefinitionList, obj.(*apiextensions_k8s_io_v1.CustomResourceDefinition)) } - return NewCustomResourceDefinitionSet(customResourceDefinitionList...) + return NewCustomResourceDefinitionSet(s.sortFunc, s.equalityFunc, customResourceDefinitionList...) } func (s *customResourceDefinitionSet) Find(id ezkube.ResourceId) (*apiextensions_k8s_io_v1.CustomResourceDefinition, error) { @@ -233,5 +307,61 @@ func (s *customResourceDefinitionSet) Clone() CustomResourceDefinitionSet { if s == nil { return nil } - return &customResourceDefinitionSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apiextensions_k8s_io_v1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &customResourceDefinitionSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *customResourceDefinitionSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *customResourceDefinitionSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/mocks/sets.go b/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/mocks/sets.go index 378c8de..179deb7 100644 --- a/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/mocks/sets.go +++ b/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockCustomResourceDefinitionSet is a mock of CustomResourceDefinitionSet interface. @@ -135,6 +136,34 @@ func (mr *MockCustomResourceDefinitionSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockCustomResourceDefinitionSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockCustomResourceDefinitionSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockCustomResourceDefinitionSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockCustomResourceDefinitionSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockCustomResourceDefinitionSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockCustomResourceDefinitionSet) Has(customResourceDefinition ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/sets.go b/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/sets.go index a051efa..3d027c7 100644 --- a/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/sets.go +++ b/pkg/api/k8s/apiextensions.k8s.io/v1beta1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type CustomResourceDefinitionSet interface { @@ -48,30 +50,98 @@ type CustomResourceDefinitionSet interface { Delta(newSet CustomResourceDefinitionSet) sksets.ResourceDelta // Create a deep copy of the current CustomResourceDefinitionSet Clone() CustomResourceDefinitionSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericCustomResourceDefinitionSet(customResourceDefinitionList []*apiextensions_k8s_io_v1beta1.CustomResourceDefinition) sksets.ResourceSet { +func makeGenericCustomResourceDefinitionSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList []*apiextensions_k8s_io_v1beta1.CustomResourceDefinition, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range customResourceDefinitionList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type customResourceDefinitionSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewCustomResourceDefinitionSet(customResourceDefinitionList ...*apiextensions_k8s_io_v1beta1.CustomResourceDefinition) CustomResourceDefinitionSet { - return &customResourceDefinitionSet{set: makeGenericCustomResourceDefinitionSet(customResourceDefinitionList)} +func NewCustomResourceDefinitionSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList ...*apiextensions_k8s_io_v1beta1.CustomResourceDefinition, +) CustomResourceDefinitionSet { + return &customResourceDefinitionSet{ + set: makeGenericCustomResourceDefinitionSet(sortFunc, equalityFunc, customResourceDefinitionList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewCustomResourceDefinitionSetFromList(customResourceDefinitionList *apiextensions_k8s_io_v1beta1.CustomResourceDefinitionList) CustomResourceDefinitionSet { +func NewCustomResourceDefinitionSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + customResourceDefinitionList *apiextensions_k8s_io_v1beta1.CustomResourceDefinitionList, +) CustomResourceDefinitionSet { list := make([]*apiextensions_k8s_io_v1beta1.CustomResourceDefinition, 0, len(customResourceDefinitionList.Items)) for idx := range customResourceDefinitionList.Items { list = append(list, &customResourceDefinitionList.Items[idx]) } - return &customResourceDefinitionSet{set: makeGenericCustomResourceDefinitionSet(list)} + return &customResourceDefinitionSet{ + set: makeGenericCustomResourceDefinitionSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *customResourceDefinitionSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *customResourceDefinitionSet) Union(set CustomResourceDefinitionSet) Cus if s == nil { return set } - return NewCustomResourceDefinitionSet(append(s.List(), set.List()...)...) + return NewCustomResourceDefinitionSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *customResourceDefinitionSet) Difference(set CustomResourceDefinitionSet) CustomResourceDefinitionSet { @@ -179,7 +249,11 @@ func (s *customResourceDefinitionSet) Difference(set CustomResourceDefinitionSet return set } newSet := s.Generic().Difference(set.Generic()) - return &customResourceDefinitionSet{set: newSet} + return &customResourceDefinitionSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *customResourceDefinitionSet) Intersection(set CustomResourceDefinitionSet) CustomResourceDefinitionSet { @@ -191,7 +265,7 @@ func (s *customResourceDefinitionSet) Intersection(set CustomResourceDefinitionS for _, obj := range newSet.List() { customResourceDefinitionList = append(customResourceDefinitionList, obj.(*apiextensions_k8s_io_v1beta1.CustomResourceDefinition)) } - return NewCustomResourceDefinitionSet(customResourceDefinitionList...) + return NewCustomResourceDefinitionSet(s.sortFunc, s.equalityFunc, customResourceDefinitionList...) } func (s *customResourceDefinitionSet) Find(id ezkube.ResourceId) (*apiextensions_k8s_io_v1beta1.CustomResourceDefinition, error) { @@ -233,5 +307,61 @@ func (s *customResourceDefinitionSet) Clone() CustomResourceDefinitionSet { if s == nil { return nil } - return &customResourceDefinitionSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apiextensions_k8s_io_v1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &customResourceDefinitionSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *customResourceDefinitionSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *customResourceDefinitionSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/apps/v1/sets/mocks/sets.go b/pkg/api/k8s/apps/v1/sets/mocks/sets.go index c3a761d..8f238de 100644 --- a/pkg/api/k8s/apps/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/apps/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/apps/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockDeploymentSet is a mock of DeploymentSet interface. @@ -135,6 +136,34 @@ func (mr *MockDeploymentSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockDeploymentSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockDeploymentSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockDeploymentSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockDeploymentSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockDeploymentSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockDeploymentSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockDeploymentSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockDeploymentSet) Has(deployment ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockReplicaSetSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockReplicaSetSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockReplicaSetSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockReplicaSetSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockReplicaSetSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockReplicaSetSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockReplicaSetSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockReplicaSetSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockReplicaSetSet) Has(replicaSet ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockDaemonSetSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockDaemonSetSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockDaemonSetSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockDaemonSetSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockDaemonSetSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockDaemonSetSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockDaemonSetSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockDaemonSetSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockDaemonSetSet) Has(daemonSet ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -903,6 +988,34 @@ func (mr *MockStatefulSetSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockStatefulSetSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockStatefulSetSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockStatefulSetSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockStatefulSetSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockStatefulSetSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockStatefulSetSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockStatefulSetSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockStatefulSetSet) Has(statefulSet ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/apps/v1/sets/sets.go b/pkg/api/k8s/apps/v1/sets/sets.go index c2a11a3..bf439c1 100644 --- a/pkg/api/k8s/apps/v1/sets/sets.go +++ b/pkg/api/k8s/apps/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type DeploymentSet interface { @@ -48,30 +50,98 @@ type DeploymentSet interface { Delta(newSet DeploymentSet) sksets.ResourceDelta // Create a deep copy of the current DeploymentSet Clone() DeploymentSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericDeploymentSet(deploymentList []*apps_v1.Deployment) sksets.ResourceSet { +func makeGenericDeploymentSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + deploymentList []*apps_v1.Deployment, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range deploymentList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type deploymentSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewDeploymentSet(deploymentList ...*apps_v1.Deployment) DeploymentSet { - return &deploymentSet{set: makeGenericDeploymentSet(deploymentList)} +func NewDeploymentSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + deploymentList ...*apps_v1.Deployment, +) DeploymentSet { + return &deploymentSet{ + set: makeGenericDeploymentSet(sortFunc, equalityFunc, deploymentList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewDeploymentSetFromList(deploymentList *apps_v1.DeploymentList) DeploymentSet { +func NewDeploymentSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + deploymentList *apps_v1.DeploymentList, +) DeploymentSet { list := make([]*apps_v1.Deployment, 0, len(deploymentList.Items)) for idx := range deploymentList.Items { list = append(list, &deploymentList.Items[idx]) } - return &deploymentSet{set: makeGenericDeploymentSet(list)} + return &deploymentSet{ + set: makeGenericDeploymentSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *deploymentSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *deploymentSet) Union(set DeploymentSet) DeploymentSet { if s == nil { return set } - return NewDeploymentSet(append(s.List(), set.List()...)...) + return NewDeploymentSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *deploymentSet) Difference(set DeploymentSet) DeploymentSet { @@ -179,7 +249,11 @@ func (s *deploymentSet) Difference(set DeploymentSet) DeploymentSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &deploymentSet{set: newSet} + return &deploymentSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *deploymentSet) Intersection(set DeploymentSet) DeploymentSet { @@ -191,7 +265,7 @@ func (s *deploymentSet) Intersection(set DeploymentSet) DeploymentSet { for _, obj := range newSet.List() { deploymentList = append(deploymentList, obj.(*apps_v1.Deployment)) } - return NewDeploymentSet(deploymentList...) + return NewDeploymentSet(s.sortFunc, s.equalityFunc, deploymentList...) } func (s *deploymentSet) Find(id ezkube.ResourceId) (*apps_v1.Deployment, error) { @@ -233,7 +307,63 @@ func (s *deploymentSet) Clone() DeploymentSet { if s == nil { return nil } - return &deploymentSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &deploymentSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *deploymentSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *deploymentSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ReplicaSetSet interface { @@ -271,30 +401,98 @@ type ReplicaSetSet interface { Delta(newSet ReplicaSetSet) sksets.ResourceDelta // Create a deep copy of the current ReplicaSetSet Clone() ReplicaSetSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericReplicaSetSet(replicaSetList []*apps_v1.ReplicaSet) sksets.ResourceSet { +func makeGenericReplicaSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + replicaSetList []*apps_v1.ReplicaSet, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range replicaSetList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type replicaSetSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewReplicaSetSet(replicaSetList ...*apps_v1.ReplicaSet) ReplicaSetSet { - return &replicaSetSet{set: makeGenericReplicaSetSet(replicaSetList)} +func NewReplicaSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + replicaSetList ...*apps_v1.ReplicaSet, +) ReplicaSetSet { + return &replicaSetSet{ + set: makeGenericReplicaSetSet(sortFunc, equalityFunc, replicaSetList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewReplicaSetSetFromList(replicaSetList *apps_v1.ReplicaSetList) ReplicaSetSet { +func NewReplicaSetSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + replicaSetList *apps_v1.ReplicaSetList, +) ReplicaSetSet { list := make([]*apps_v1.ReplicaSet, 0, len(replicaSetList.Items)) for idx := range replicaSetList.Items { list = append(list, &replicaSetList.Items[idx]) } - return &replicaSetSet{set: makeGenericReplicaSetSet(list)} + return &replicaSetSet{ + set: makeGenericReplicaSetSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *replicaSetSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *replicaSetSet) Union(set ReplicaSetSet) ReplicaSetSet { if s == nil { return set } - return NewReplicaSetSet(append(s.List(), set.List()...)...) + return NewReplicaSetSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *replicaSetSet) Difference(set ReplicaSetSet) ReplicaSetSet { @@ -402,7 +600,11 @@ func (s *replicaSetSet) Difference(set ReplicaSetSet) ReplicaSetSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &replicaSetSet{set: newSet} + return &replicaSetSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *replicaSetSet) Intersection(set ReplicaSetSet) ReplicaSetSet { @@ -414,7 +616,7 @@ func (s *replicaSetSet) Intersection(set ReplicaSetSet) ReplicaSetSet { for _, obj := range newSet.List() { replicaSetList = append(replicaSetList, obj.(*apps_v1.ReplicaSet)) } - return NewReplicaSetSet(replicaSetList...) + return NewReplicaSetSet(s.sortFunc, s.equalityFunc, replicaSetList...) } func (s *replicaSetSet) Find(id ezkube.ResourceId) (*apps_v1.ReplicaSet, error) { @@ -456,7 +658,63 @@ func (s *replicaSetSet) Clone() ReplicaSetSet { if s == nil { return nil } - return &replicaSetSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &replicaSetSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *replicaSetSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *replicaSetSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type DaemonSetSet interface { @@ -494,30 +752,98 @@ type DaemonSetSet interface { Delta(newSet DaemonSetSet) sksets.ResourceDelta // Create a deep copy of the current DaemonSetSet Clone() DaemonSetSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericDaemonSetSet(daemonSetList []*apps_v1.DaemonSet) sksets.ResourceSet { +func makeGenericDaemonSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + daemonSetList []*apps_v1.DaemonSet, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range daemonSetList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type daemonSetSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewDaemonSetSet(daemonSetList ...*apps_v1.DaemonSet) DaemonSetSet { - return &daemonSetSet{set: makeGenericDaemonSetSet(daemonSetList)} +func NewDaemonSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + daemonSetList ...*apps_v1.DaemonSet, +) DaemonSetSet { + return &daemonSetSet{ + set: makeGenericDaemonSetSet(sortFunc, equalityFunc, daemonSetList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewDaemonSetSetFromList(daemonSetList *apps_v1.DaemonSetList) DaemonSetSet { +func NewDaemonSetSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + daemonSetList *apps_v1.DaemonSetList, +) DaemonSetSet { list := make([]*apps_v1.DaemonSet, 0, len(daemonSetList.Items)) for idx := range daemonSetList.Items { list = append(list, &daemonSetList.Items[idx]) } - return &daemonSetSet{set: makeGenericDaemonSetSet(list)} + return &daemonSetSet{ + set: makeGenericDaemonSetSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *daemonSetSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *daemonSetSet) Union(set DaemonSetSet) DaemonSetSet { if s == nil { return set } - return NewDaemonSetSet(append(s.List(), set.List()...)...) + return NewDaemonSetSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *daemonSetSet) Difference(set DaemonSetSet) DaemonSetSet { @@ -625,7 +951,11 @@ func (s *daemonSetSet) Difference(set DaemonSetSet) DaemonSetSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &daemonSetSet{set: newSet} + return &daemonSetSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *daemonSetSet) Intersection(set DaemonSetSet) DaemonSetSet { @@ -637,7 +967,7 @@ func (s *daemonSetSet) Intersection(set DaemonSetSet) DaemonSetSet { for _, obj := range newSet.List() { daemonSetList = append(daemonSetList, obj.(*apps_v1.DaemonSet)) } - return NewDaemonSetSet(daemonSetList...) + return NewDaemonSetSet(s.sortFunc, s.equalityFunc, daemonSetList...) } func (s *daemonSetSet) Find(id ezkube.ResourceId) (*apps_v1.DaemonSet, error) { @@ -679,7 +1009,63 @@ func (s *daemonSetSet) Clone() DaemonSetSet { if s == nil { return nil } - return &daemonSetSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.DaemonSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &daemonSetSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *daemonSetSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *daemonSetSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type StatefulSetSet interface { @@ -717,30 +1103,98 @@ type StatefulSetSet interface { Delta(newSet StatefulSetSet) sksets.ResourceDelta // Create a deep copy of the current StatefulSetSet Clone() StatefulSetSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericStatefulSetSet(statefulSetList []*apps_v1.StatefulSet) sksets.ResourceSet { +func makeGenericStatefulSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + statefulSetList []*apps_v1.StatefulSet, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range statefulSetList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type statefulSetSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewStatefulSetSet(statefulSetList ...*apps_v1.StatefulSet) StatefulSetSet { - return &statefulSetSet{set: makeGenericStatefulSetSet(statefulSetList)} +func NewStatefulSetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + statefulSetList ...*apps_v1.StatefulSet, +) StatefulSetSet { + return &statefulSetSet{ + set: makeGenericStatefulSetSet(sortFunc, equalityFunc, statefulSetList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewStatefulSetSetFromList(statefulSetList *apps_v1.StatefulSetList) StatefulSetSet { +func NewStatefulSetSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + statefulSetList *apps_v1.StatefulSetList, +) StatefulSetSet { list := make([]*apps_v1.StatefulSet, 0, len(statefulSetList.Items)) for idx := range statefulSetList.Items { list = append(list, &statefulSetList.Items[idx]) } - return &statefulSetSet{set: makeGenericStatefulSetSet(list)} + return &statefulSetSet{ + set: makeGenericStatefulSetSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *statefulSetSet) Keys() sets.String { @@ -840,7 +1294,7 @@ func (s *statefulSetSet) Union(set StatefulSetSet) StatefulSetSet { if s == nil { return set } - return NewStatefulSetSet(append(s.List(), set.List()...)...) + return NewStatefulSetSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *statefulSetSet) Difference(set StatefulSetSet) StatefulSetSet { @@ -848,7 +1302,11 @@ func (s *statefulSetSet) Difference(set StatefulSetSet) StatefulSetSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &statefulSetSet{set: newSet} + return &statefulSetSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *statefulSetSet) Intersection(set StatefulSetSet) StatefulSetSet { @@ -860,7 +1318,7 @@ func (s *statefulSetSet) Intersection(set StatefulSetSet) StatefulSetSet { for _, obj := range newSet.List() { statefulSetList = append(statefulSetList, obj.(*apps_v1.StatefulSet)) } - return NewStatefulSetSet(statefulSetList...) + return NewStatefulSetSet(s.sortFunc, s.equalityFunc, statefulSetList...) } func (s *statefulSetSet) Find(id ezkube.ResourceId) (*apps_v1.StatefulSet, error) { @@ -902,5 +1360,61 @@ func (s *statefulSetSet) Clone() StatefulSetSet { if s == nil { return nil } - return &statefulSetSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &apps_v1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &statefulSetSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *statefulSetSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *statefulSetSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/batch/v1/sets/mocks/sets.go b/pkg/api/k8s/batch/v1/sets/mocks/sets.go index 05d92af..683d0ac 100644 --- a/pkg/api/k8s/batch/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/batch/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/batch/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockJobSet is a mock of JobSet interface. @@ -135,6 +136,34 @@ func (mr *MockJobSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockJobSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockJobSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockJobSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockJobSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockJobSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockJobSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockJobSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockJobSet) Has(job ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/batch/v1/sets/sets.go b/pkg/api/k8s/batch/v1/sets/sets.go index 2d7a1a2..8797299 100644 --- a/pkg/api/k8s/batch/v1/sets/sets.go +++ b/pkg/api/k8s/batch/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type JobSet interface { @@ -48,30 +50,98 @@ type JobSet interface { Delta(newSet JobSet) sksets.ResourceDelta // Create a deep copy of the current JobSet Clone() JobSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericJobSet(jobList []*batch_v1.Job) sksets.ResourceSet { +func makeGenericJobSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + jobList []*batch_v1.Job, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range jobList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type jobSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewJobSet(jobList ...*batch_v1.Job) JobSet { - return &jobSet{set: makeGenericJobSet(jobList)} +func NewJobSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + jobList ...*batch_v1.Job, +) JobSet { + return &jobSet{ + set: makeGenericJobSet(sortFunc, equalityFunc, jobList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewJobSetFromList(jobList *batch_v1.JobList) JobSet { +func NewJobSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + jobList *batch_v1.JobList, +) JobSet { list := make([]*batch_v1.Job, 0, len(jobList.Items)) for idx := range jobList.Items { list = append(list, &jobList.Items[idx]) } - return &jobSet{set: makeGenericJobSet(list)} + return &jobSet{ + set: makeGenericJobSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *jobSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *jobSet) Union(set JobSet) JobSet { if s == nil { return set } - return NewJobSet(append(s.List(), set.List()...)...) + return NewJobSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *jobSet) Difference(set JobSet) JobSet { @@ -179,7 +249,11 @@ func (s *jobSet) Difference(set JobSet) JobSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &jobSet{set: newSet} + return &jobSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *jobSet) Intersection(set JobSet) JobSet { @@ -191,7 +265,7 @@ func (s *jobSet) Intersection(set JobSet) JobSet { for _, obj := range newSet.List() { jobList = append(jobList, obj.(*batch_v1.Job)) } - return NewJobSet(jobList...) + return NewJobSet(s.sortFunc, s.equalityFunc, jobList...) } func (s *jobSet) Find(id ezkube.ResourceId) (*batch_v1.Job, error) { @@ -233,5 +307,61 @@ func (s *jobSet) Clone() JobSet { if s == nil { return nil } - return &jobSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &batch_v1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &jobSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *jobSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *jobSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/mocks/sets.go b/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/mocks/sets.go index 0382e5b..74d95c3 100644 --- a/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/mocks/sets.go +++ b/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1beta1 "k8s.io/api/certificates/v1beta1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockCertificateSigningRequestSet is a mock of CertificateSigningRequestSet interface. @@ -135,6 +136,34 @@ func (mr *MockCertificateSigningRequestSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockCertificateSigningRequestSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockCertificateSigningRequestSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockCertificateSigningRequestSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockCertificateSigningRequestSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockCertificateSigningRequestSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockCertificateSigningRequestSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockCertificateSigningRequestSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockCertificateSigningRequestSet) Has(certificateSigningRequest ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/sets.go b/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/sets.go index 024e191..0aead12 100644 --- a/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/sets.go +++ b/pkg/api/k8s/certificates.k8s.io/v1beta1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type CertificateSigningRequestSet interface { @@ -48,30 +50,98 @@ type CertificateSigningRequestSet interface { Delta(newSet CertificateSigningRequestSet) sksets.ResourceDelta // Create a deep copy of the current CertificateSigningRequestSet Clone() CertificateSigningRequestSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericCertificateSigningRequestSet(certificateSigningRequestList []*certificates_k8s_io_v1beta1.CertificateSigningRequest) sksets.ResourceSet { +func makeGenericCertificateSigningRequestSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + certificateSigningRequestList []*certificates_k8s_io_v1beta1.CertificateSigningRequest, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range certificateSigningRequestList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type certificateSigningRequestSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewCertificateSigningRequestSet(certificateSigningRequestList ...*certificates_k8s_io_v1beta1.CertificateSigningRequest) CertificateSigningRequestSet { - return &certificateSigningRequestSet{set: makeGenericCertificateSigningRequestSet(certificateSigningRequestList)} +func NewCertificateSigningRequestSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + certificateSigningRequestList ...*certificates_k8s_io_v1beta1.CertificateSigningRequest, +) CertificateSigningRequestSet { + return &certificateSigningRequestSet{ + set: makeGenericCertificateSigningRequestSet(sortFunc, equalityFunc, certificateSigningRequestList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewCertificateSigningRequestSetFromList(certificateSigningRequestList *certificates_k8s_io_v1beta1.CertificateSigningRequestList) CertificateSigningRequestSet { +func NewCertificateSigningRequestSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + certificateSigningRequestList *certificates_k8s_io_v1beta1.CertificateSigningRequestList, +) CertificateSigningRequestSet { list := make([]*certificates_k8s_io_v1beta1.CertificateSigningRequest, 0, len(certificateSigningRequestList.Items)) for idx := range certificateSigningRequestList.Items { list = append(list, &certificateSigningRequestList.Items[idx]) } - return &certificateSigningRequestSet{set: makeGenericCertificateSigningRequestSet(list)} + return &certificateSigningRequestSet{ + set: makeGenericCertificateSigningRequestSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *certificateSigningRequestSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *certificateSigningRequestSet) Union(set CertificateSigningRequestSet) C if s == nil { return set } - return NewCertificateSigningRequestSet(append(s.List(), set.List()...)...) + return NewCertificateSigningRequestSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *certificateSigningRequestSet) Difference(set CertificateSigningRequestSet) CertificateSigningRequestSet { @@ -179,7 +249,11 @@ func (s *certificateSigningRequestSet) Difference(set CertificateSigningRequestS return set } newSet := s.Generic().Difference(set.Generic()) - return &certificateSigningRequestSet{set: newSet} + return &certificateSigningRequestSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *certificateSigningRequestSet) Intersection(set CertificateSigningRequestSet) CertificateSigningRequestSet { @@ -191,7 +265,7 @@ func (s *certificateSigningRequestSet) Intersection(set CertificateSigningReques for _, obj := range newSet.List() { certificateSigningRequestList = append(certificateSigningRequestList, obj.(*certificates_k8s_io_v1beta1.CertificateSigningRequest)) } - return NewCertificateSigningRequestSet(certificateSigningRequestList...) + return NewCertificateSigningRequestSet(s.sortFunc, s.equalityFunc, certificateSigningRequestList...) } func (s *certificateSigningRequestSet) Find(id ezkube.ResourceId) (*certificates_k8s_io_v1beta1.CertificateSigningRequest, error) { @@ -233,5 +307,61 @@ func (s *certificateSigningRequestSet) Clone() CertificateSigningRequestSet { if s == nil { return nil } - return &certificateSigningRequestSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &certificates_k8s_io_v1beta1.CertificateSigningRequest{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &certificateSigningRequestSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *certificateSigningRequestSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *certificateSigningRequestSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/core/v1/sets/mocks/sets.go b/pkg/api/k8s/core/v1/sets/mocks/sets.go index ddec194..e7592c3 100644 --- a/pkg/api/k8s/core/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/core/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/core/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockSecretSet is a mock of SecretSet interface. @@ -135,6 +136,34 @@ func (mr *MockSecretSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockSecretSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockSecretSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockSecretSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockSecretSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockSecretSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockSecretSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockSecretSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockSecretSet) Has(secret ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockServiceAccountSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockServiceAccountSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockServiceAccountSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockServiceAccountSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockServiceAccountSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockServiceAccountSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockServiceAccountSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockServiceAccountSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockServiceAccountSet) Has(serviceAccount ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockConfigMapSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockConfigMapSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockConfigMapSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockConfigMapSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockConfigMapSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockConfigMapSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockConfigMapSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockConfigMapSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockConfigMapSet) Has(configMap ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -903,6 +988,34 @@ func (mr *MockServiceSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockServiceSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockServiceSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockServiceSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockServiceSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockServiceSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockServiceSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockServiceSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockServiceSet) Has(service ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1159,6 +1272,34 @@ func (mr *MockPodSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockPodSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockPodSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockPodSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockPodSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockPodSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockPodSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockPodSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockPodSet) Has(pod ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1415,6 +1556,34 @@ func (mr *MockEndpointsSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockEndpointsSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockEndpointsSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockEndpointsSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockEndpointsSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockEndpointsSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockEndpointsSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockEndpointsSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockEndpointsSet) Has(endpoints ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1671,6 +1840,34 @@ func (mr *MockNamespaceSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockNamespaceSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockNamespaceSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockNamespaceSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockNamespaceSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockNamespaceSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockNamespaceSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockNamespaceSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockNamespaceSet) Has(namespace ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -1927,6 +2124,34 @@ func (mr *MockNodeSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockNodeSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockNodeSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockNodeSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockNodeSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockNodeSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockNodeSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockNodeSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockNodeSet) Has(node ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/core/v1/sets/sets.go b/pkg/api/k8s/core/v1/sets/sets.go index 75ccb3d..c5d56da 100644 --- a/pkg/api/k8s/core/v1/sets/sets.go +++ b/pkg/api/k8s/core/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type SecretSet interface { @@ -48,30 +50,98 @@ type SecretSet interface { Delta(newSet SecretSet) sksets.ResourceDelta // Create a deep copy of the current SecretSet Clone() SecretSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericSecretSet(secretList []*v1.Secret) sksets.ResourceSet { +func makeGenericSecretSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + secretList []*v1.Secret, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range secretList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type secretSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewSecretSet(secretList ...*v1.Secret) SecretSet { - return &secretSet{set: makeGenericSecretSet(secretList)} +func NewSecretSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + secretList ...*v1.Secret, +) SecretSet { + return &secretSet{ + set: makeGenericSecretSet(sortFunc, equalityFunc, secretList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewSecretSetFromList(secretList *v1.SecretList) SecretSet { +func NewSecretSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + secretList *v1.SecretList, +) SecretSet { list := make([]*v1.Secret, 0, len(secretList.Items)) for idx := range secretList.Items { list = append(list, &secretList.Items[idx]) } - return &secretSet{set: makeGenericSecretSet(list)} + return &secretSet{ + set: makeGenericSecretSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *secretSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *secretSet) Union(set SecretSet) SecretSet { if s == nil { return set } - return NewSecretSet(append(s.List(), set.List()...)...) + return NewSecretSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *secretSet) Difference(set SecretSet) SecretSet { @@ -179,7 +249,11 @@ func (s *secretSet) Difference(set SecretSet) SecretSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &secretSet{set: newSet} + return &secretSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *secretSet) Intersection(set SecretSet) SecretSet { @@ -191,7 +265,7 @@ func (s *secretSet) Intersection(set SecretSet) SecretSet { for _, obj := range newSet.List() { secretList = append(secretList, obj.(*v1.Secret)) } - return NewSecretSet(secretList...) + return NewSecretSet(s.sortFunc, s.equalityFunc, secretList...) } func (s *secretSet) Find(id ezkube.ResourceId) (*v1.Secret, error) { @@ -233,7 +307,63 @@ func (s *secretSet) Clone() SecretSet { if s == nil { return nil } - return &secretSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &secretSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *secretSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *secretSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ServiceAccountSet interface { @@ -271,30 +401,98 @@ type ServiceAccountSet interface { Delta(newSet ServiceAccountSet) sksets.ResourceDelta // Create a deep copy of the current ServiceAccountSet Clone() ServiceAccountSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericServiceAccountSet(serviceAccountList []*v1.ServiceAccount) sksets.ResourceSet { +func makeGenericServiceAccountSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceAccountList []*v1.ServiceAccount, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range serviceAccountList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type serviceAccountSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewServiceAccountSet(serviceAccountList ...*v1.ServiceAccount) ServiceAccountSet { - return &serviceAccountSet{set: makeGenericServiceAccountSet(serviceAccountList)} +func NewServiceAccountSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceAccountList ...*v1.ServiceAccount, +) ServiceAccountSet { + return &serviceAccountSet{ + set: makeGenericServiceAccountSet(sortFunc, equalityFunc, serviceAccountList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewServiceAccountSetFromList(serviceAccountList *v1.ServiceAccountList) ServiceAccountSet { +func NewServiceAccountSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceAccountList *v1.ServiceAccountList, +) ServiceAccountSet { list := make([]*v1.ServiceAccount, 0, len(serviceAccountList.Items)) for idx := range serviceAccountList.Items { list = append(list, &serviceAccountList.Items[idx]) } - return &serviceAccountSet{set: makeGenericServiceAccountSet(list)} + return &serviceAccountSet{ + set: makeGenericServiceAccountSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *serviceAccountSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *serviceAccountSet) Union(set ServiceAccountSet) ServiceAccountSet { if s == nil { return set } - return NewServiceAccountSet(append(s.List(), set.List()...)...) + return NewServiceAccountSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *serviceAccountSet) Difference(set ServiceAccountSet) ServiceAccountSet { @@ -402,7 +600,11 @@ func (s *serviceAccountSet) Difference(set ServiceAccountSet) ServiceAccountSet return set } newSet := s.Generic().Difference(set.Generic()) - return &serviceAccountSet{set: newSet} + return &serviceAccountSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *serviceAccountSet) Intersection(set ServiceAccountSet) ServiceAccountSet { @@ -414,7 +616,7 @@ func (s *serviceAccountSet) Intersection(set ServiceAccountSet) ServiceAccountSe for _, obj := range newSet.List() { serviceAccountList = append(serviceAccountList, obj.(*v1.ServiceAccount)) } - return NewServiceAccountSet(serviceAccountList...) + return NewServiceAccountSet(s.sortFunc, s.equalityFunc, serviceAccountList...) } func (s *serviceAccountSet) Find(id ezkube.ResourceId) (*v1.ServiceAccount, error) { @@ -456,7 +658,63 @@ func (s *serviceAccountSet) Clone() ServiceAccountSet { if s == nil { return nil } - return &serviceAccountSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &serviceAccountSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *serviceAccountSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *serviceAccountSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ConfigMapSet interface { @@ -494,30 +752,98 @@ type ConfigMapSet interface { Delta(newSet ConfigMapSet) sksets.ResourceDelta // Create a deep copy of the current ConfigMapSet Clone() ConfigMapSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericConfigMapSet(configMapList []*v1.ConfigMap) sksets.ResourceSet { +func makeGenericConfigMapSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + configMapList []*v1.ConfigMap, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range configMapList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type configMapSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewConfigMapSet(configMapList ...*v1.ConfigMap) ConfigMapSet { - return &configMapSet{set: makeGenericConfigMapSet(configMapList)} +func NewConfigMapSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + configMapList ...*v1.ConfigMap, +) ConfigMapSet { + return &configMapSet{ + set: makeGenericConfigMapSet(sortFunc, equalityFunc, configMapList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewConfigMapSetFromList(configMapList *v1.ConfigMapList) ConfigMapSet { +func NewConfigMapSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + configMapList *v1.ConfigMapList, +) ConfigMapSet { list := make([]*v1.ConfigMap, 0, len(configMapList.Items)) for idx := range configMapList.Items { list = append(list, &configMapList.Items[idx]) } - return &configMapSet{set: makeGenericConfigMapSet(list)} + return &configMapSet{ + set: makeGenericConfigMapSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *configMapSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *configMapSet) Union(set ConfigMapSet) ConfigMapSet { if s == nil { return set } - return NewConfigMapSet(append(s.List(), set.List()...)...) + return NewConfigMapSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *configMapSet) Difference(set ConfigMapSet) ConfigMapSet { @@ -625,7 +951,11 @@ func (s *configMapSet) Difference(set ConfigMapSet) ConfigMapSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &configMapSet{set: newSet} + return &configMapSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *configMapSet) Intersection(set ConfigMapSet) ConfigMapSet { @@ -637,7 +967,7 @@ func (s *configMapSet) Intersection(set ConfigMapSet) ConfigMapSet { for _, obj := range newSet.List() { configMapList = append(configMapList, obj.(*v1.ConfigMap)) } - return NewConfigMapSet(configMapList...) + return NewConfigMapSet(s.sortFunc, s.equalityFunc, configMapList...) } func (s *configMapSet) Find(id ezkube.ResourceId) (*v1.ConfigMap, error) { @@ -679,7 +1009,63 @@ func (s *configMapSet) Clone() ConfigMapSet { if s == nil { return nil } - return &configMapSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &configMapSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *configMapSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *configMapSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ServiceSet interface { @@ -717,30 +1103,98 @@ type ServiceSet interface { Delta(newSet ServiceSet) sksets.ResourceDelta // Create a deep copy of the current ServiceSet Clone() ServiceSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericServiceSet(serviceList []*v1.Service) sksets.ResourceSet { +func makeGenericServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceList []*v1.Service, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range serviceList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type serviceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewServiceSet(serviceList ...*v1.Service) ServiceSet { - return &serviceSet{set: makeGenericServiceSet(serviceList)} +func NewServiceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceList ...*v1.Service, +) ServiceSet { + return &serviceSet{ + set: makeGenericServiceSet(sortFunc, equalityFunc, serviceList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewServiceSetFromList(serviceList *v1.ServiceList) ServiceSet { +func NewServiceSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + serviceList *v1.ServiceList, +) ServiceSet { list := make([]*v1.Service, 0, len(serviceList.Items)) for idx := range serviceList.Items { list = append(list, &serviceList.Items[idx]) } - return &serviceSet{set: makeGenericServiceSet(list)} + return &serviceSet{ + set: makeGenericServiceSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *serviceSet) Keys() sets.String { @@ -840,7 +1294,7 @@ func (s *serviceSet) Union(set ServiceSet) ServiceSet { if s == nil { return set } - return NewServiceSet(append(s.List(), set.List()...)...) + return NewServiceSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *serviceSet) Difference(set ServiceSet) ServiceSet { @@ -848,7 +1302,11 @@ func (s *serviceSet) Difference(set ServiceSet) ServiceSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &serviceSet{set: newSet} + return &serviceSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *serviceSet) Intersection(set ServiceSet) ServiceSet { @@ -860,7 +1318,7 @@ func (s *serviceSet) Intersection(set ServiceSet) ServiceSet { for _, obj := range newSet.List() { serviceList = append(serviceList, obj.(*v1.Service)) } - return NewServiceSet(serviceList...) + return NewServiceSet(s.sortFunc, s.equalityFunc, serviceList...) } func (s *serviceSet) Find(id ezkube.ResourceId) (*v1.Service, error) { @@ -902,7 +1360,63 @@ func (s *serviceSet) Clone() ServiceSet { if s == nil { return nil } - return &serviceSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &serviceSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *serviceSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *serviceSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type PodSet interface { @@ -940,30 +1454,98 @@ type PodSet interface { Delta(newSet PodSet) sksets.ResourceDelta // Create a deep copy of the current PodSet Clone() PodSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericPodSet(podList []*v1.Pod) sksets.ResourceSet { +func makeGenericPodSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + podList []*v1.Pod, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range podList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type podSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewPodSet(podList ...*v1.Pod) PodSet { - return &podSet{set: makeGenericPodSet(podList)} +func NewPodSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + podList ...*v1.Pod, +) PodSet { + return &podSet{ + set: makeGenericPodSet(sortFunc, equalityFunc, podList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewPodSetFromList(podList *v1.PodList) PodSet { +func NewPodSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + podList *v1.PodList, +) PodSet { list := make([]*v1.Pod, 0, len(podList.Items)) for idx := range podList.Items { list = append(list, &podList.Items[idx]) } - return &podSet{set: makeGenericPodSet(list)} + return &podSet{ + set: makeGenericPodSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *podSet) Keys() sets.String { @@ -1063,7 +1645,7 @@ func (s *podSet) Union(set PodSet) PodSet { if s == nil { return set } - return NewPodSet(append(s.List(), set.List()...)...) + return NewPodSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *podSet) Difference(set PodSet) PodSet { @@ -1071,7 +1653,11 @@ func (s *podSet) Difference(set PodSet) PodSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &podSet{set: newSet} + return &podSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *podSet) Intersection(set PodSet) PodSet { @@ -1083,7 +1669,7 @@ func (s *podSet) Intersection(set PodSet) PodSet { for _, obj := range newSet.List() { podList = append(podList, obj.(*v1.Pod)) } - return NewPodSet(podList...) + return NewPodSet(s.sortFunc, s.equalityFunc, podList...) } func (s *podSet) Find(id ezkube.ResourceId) (*v1.Pod, error) { @@ -1125,7 +1711,63 @@ func (s *podSet) Clone() PodSet { if s == nil { return nil } - return &podSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &podSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *podSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *podSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type EndpointsSet interface { @@ -1163,30 +1805,98 @@ type EndpointsSet interface { Delta(newSet EndpointsSet) sksets.ResourceDelta // Create a deep copy of the current EndpointsSet Clone() EndpointsSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericEndpointsSet(endpointsList []*v1.Endpoints) sksets.ResourceSet { +func makeGenericEndpointsSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + endpointsList []*v1.Endpoints, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range endpointsList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type endpointsSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewEndpointsSet(endpointsList ...*v1.Endpoints) EndpointsSet { - return &endpointsSet{set: makeGenericEndpointsSet(endpointsList)} +func NewEndpointsSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + endpointsList ...*v1.Endpoints, +) EndpointsSet { + return &endpointsSet{ + set: makeGenericEndpointsSet(sortFunc, equalityFunc, endpointsList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewEndpointsSetFromList(endpointsList *v1.EndpointsList) EndpointsSet { +func NewEndpointsSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + endpointsList *v1.EndpointsList, +) EndpointsSet { list := make([]*v1.Endpoints, 0, len(endpointsList.Items)) for idx := range endpointsList.Items { list = append(list, &endpointsList.Items[idx]) } - return &endpointsSet{set: makeGenericEndpointsSet(list)} + return &endpointsSet{ + set: makeGenericEndpointsSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *endpointsSet) Keys() sets.String { @@ -1286,7 +1996,7 @@ func (s *endpointsSet) Union(set EndpointsSet) EndpointsSet { if s == nil { return set } - return NewEndpointsSet(append(s.List(), set.List()...)...) + return NewEndpointsSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *endpointsSet) Difference(set EndpointsSet) EndpointsSet { @@ -1294,7 +2004,11 @@ func (s *endpointsSet) Difference(set EndpointsSet) EndpointsSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &endpointsSet{set: newSet} + return &endpointsSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *endpointsSet) Intersection(set EndpointsSet) EndpointsSet { @@ -1306,7 +2020,7 @@ func (s *endpointsSet) Intersection(set EndpointsSet) EndpointsSet { for _, obj := range newSet.List() { endpointsList = append(endpointsList, obj.(*v1.Endpoints)) } - return NewEndpointsSet(endpointsList...) + return NewEndpointsSet(s.sortFunc, s.equalityFunc, endpointsList...) } func (s *endpointsSet) Find(id ezkube.ResourceId) (*v1.Endpoints, error) { @@ -1348,7 +2062,63 @@ func (s *endpointsSet) Clone() EndpointsSet { if s == nil { return nil } - return &endpointsSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &endpointsSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *endpointsSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *endpointsSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type NamespaceSet interface { @@ -1386,30 +2156,98 @@ type NamespaceSet interface { Delta(newSet NamespaceSet) sksets.ResourceDelta // Create a deep copy of the current NamespaceSet Clone() NamespaceSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericNamespaceSet(namespaceList []*v1.Namespace) sksets.ResourceSet { +func makeGenericNamespaceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + namespaceList []*v1.Namespace, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range namespaceList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type namespaceSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewNamespaceSet(namespaceList ...*v1.Namespace) NamespaceSet { - return &namespaceSet{set: makeGenericNamespaceSet(namespaceList)} +func NewNamespaceSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + namespaceList ...*v1.Namespace, +) NamespaceSet { + return &namespaceSet{ + set: makeGenericNamespaceSet(sortFunc, equalityFunc, namespaceList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewNamespaceSetFromList(namespaceList *v1.NamespaceList) NamespaceSet { +func NewNamespaceSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + namespaceList *v1.NamespaceList, +) NamespaceSet { list := make([]*v1.Namespace, 0, len(namespaceList.Items)) for idx := range namespaceList.Items { list = append(list, &namespaceList.Items[idx]) } - return &namespaceSet{set: makeGenericNamespaceSet(list)} + return &namespaceSet{ + set: makeGenericNamespaceSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *namespaceSet) Keys() sets.String { @@ -1509,7 +2347,7 @@ func (s *namespaceSet) Union(set NamespaceSet) NamespaceSet { if s == nil { return set } - return NewNamespaceSet(append(s.List(), set.List()...)...) + return NewNamespaceSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *namespaceSet) Difference(set NamespaceSet) NamespaceSet { @@ -1517,7 +2355,11 @@ func (s *namespaceSet) Difference(set NamespaceSet) NamespaceSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &namespaceSet{set: newSet} + return &namespaceSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *namespaceSet) Intersection(set NamespaceSet) NamespaceSet { @@ -1529,7 +2371,7 @@ func (s *namespaceSet) Intersection(set NamespaceSet) NamespaceSet { for _, obj := range newSet.List() { namespaceList = append(namespaceList, obj.(*v1.Namespace)) } - return NewNamespaceSet(namespaceList...) + return NewNamespaceSet(s.sortFunc, s.equalityFunc, namespaceList...) } func (s *namespaceSet) Find(id ezkube.ResourceId) (*v1.Namespace, error) { @@ -1571,7 +2413,63 @@ func (s *namespaceSet) Clone() NamespaceSet { if s == nil { return nil } - return &namespaceSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &namespaceSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *namespaceSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *namespaceSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type NodeSet interface { @@ -1609,30 +2507,98 @@ type NodeSet interface { Delta(newSet NodeSet) sksets.ResourceDelta // Create a deep copy of the current NodeSet Clone() NodeSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericNodeSet(nodeList []*v1.Node) sksets.ResourceSet { +func makeGenericNodeSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + nodeList []*v1.Node, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range nodeList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type nodeSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewNodeSet(nodeList ...*v1.Node) NodeSet { - return &nodeSet{set: makeGenericNodeSet(nodeList)} +func NewNodeSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + nodeList ...*v1.Node, +) NodeSet { + return &nodeSet{ + set: makeGenericNodeSet(sortFunc, equalityFunc, nodeList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewNodeSetFromList(nodeList *v1.NodeList) NodeSet { +func NewNodeSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + nodeList *v1.NodeList, +) NodeSet { list := make([]*v1.Node, 0, len(nodeList.Items)) for idx := range nodeList.Items { list = append(list, &nodeList.Items[idx]) } - return &nodeSet{set: makeGenericNodeSet(list)} + return &nodeSet{ + set: makeGenericNodeSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *nodeSet) Keys() sets.String { @@ -1732,7 +2698,7 @@ func (s *nodeSet) Union(set NodeSet) NodeSet { if s == nil { return set } - return NewNodeSet(append(s.List(), set.List()...)...) + return NewNodeSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *nodeSet) Difference(set NodeSet) NodeSet { @@ -1740,7 +2706,11 @@ func (s *nodeSet) Difference(set NodeSet) NodeSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &nodeSet{set: newSet} + return &nodeSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *nodeSet) Intersection(set NodeSet) NodeSet { @@ -1752,7 +2722,7 @@ func (s *nodeSet) Intersection(set NodeSet) NodeSet { for _, obj := range newSet.List() { nodeList = append(nodeList, obj.(*v1.Node)) } - return NewNodeSet(nodeList...) + return NewNodeSet(s.sortFunc, s.equalityFunc, nodeList...) } func (s *nodeSet) Find(id ezkube.ResourceId) (*v1.Node, error) { @@ -1794,5 +2764,61 @@ func (s *nodeSet) Clone() NodeSet { if s == nil { return nil } - return &nodeSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &v1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &nodeSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *nodeSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *nodeSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/mocks/sets.go b/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/mocks/sets.go index 9d91b1f..ebea244 100644 --- a/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/mocks/sets.go +++ b/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/mocks/sets.go @@ -12,6 +12,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" ) @@ -135,6 +136,34 @@ func (mr *MockGatewaySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockGatewaySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockGatewaySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockGatewaySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockGatewaySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockGatewaySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockGatewaySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockGatewaySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockGatewaySet) Has(gateway ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockGatewayClassSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockGatewayClassSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockGatewayClassSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockGatewayClassSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockGatewayClassSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockGatewayClassSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockGatewayClassSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockGatewayClassSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockGatewayClassSet) Has(gatewayClass ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockHTTPRouteSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockHTTPRouteSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockHTTPRouteSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockHTTPRouteSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockHTTPRouteSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockHTTPRouteSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockHTTPRouteSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockHTTPRouteSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockHTTPRouteSet) Has(hTTPRoute ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/sets.go b/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/sets.go index bfa04d4..3a602c1 100644 --- a/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/sets.go +++ b/pkg/api/k8s/gateway.networking.k8s.io/v1beta1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type GatewaySet interface { @@ -48,30 +50,98 @@ type GatewaySet interface { Delta(newSet GatewaySet) sksets.ResourceDelta // Create a deep copy of the current GatewaySet Clone() GatewaySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericGatewaySet(gatewayList []*gateway_networking_k8s_io_v1beta1.Gateway) sksets.ResourceSet { +func makeGenericGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList []*gateway_networking_k8s_io_v1beta1.Gateway, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range gatewayList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type gatewaySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewGatewaySet(gatewayList ...*gateway_networking_k8s_io_v1beta1.Gateway) GatewaySet { - return &gatewaySet{set: makeGenericGatewaySet(gatewayList)} +func NewGatewaySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList ...*gateway_networking_k8s_io_v1beta1.Gateway, +) GatewaySet { + return &gatewaySet{ + set: makeGenericGatewaySet(sortFunc, equalityFunc, gatewayList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewGatewaySetFromList(gatewayList *gateway_networking_k8s_io_v1beta1.GatewayList) GatewaySet { +func NewGatewaySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayList *gateway_networking_k8s_io_v1beta1.GatewayList, +) GatewaySet { list := make([]*gateway_networking_k8s_io_v1beta1.Gateway, 0, len(gatewayList.Items)) for idx := range gatewayList.Items { list = append(list, &gatewayList.Items[idx]) } - return &gatewaySet{set: makeGenericGatewaySet(list)} + return &gatewaySet{ + set: makeGenericGatewaySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *gatewaySet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *gatewaySet) Union(set GatewaySet) GatewaySet { if s == nil { return set } - return NewGatewaySet(append(s.List(), set.List()...)...) + return NewGatewaySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *gatewaySet) Difference(set GatewaySet) GatewaySet { @@ -179,7 +249,11 @@ func (s *gatewaySet) Difference(set GatewaySet) GatewaySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &gatewaySet{set: newSet} + return &gatewaySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *gatewaySet) Intersection(set GatewaySet) GatewaySet { @@ -191,7 +265,7 @@ func (s *gatewaySet) Intersection(set GatewaySet) GatewaySet { for _, obj := range newSet.List() { gatewayList = append(gatewayList, obj.(*gateway_networking_k8s_io_v1beta1.Gateway)) } - return NewGatewaySet(gatewayList...) + return NewGatewaySet(s.sortFunc, s.equalityFunc, gatewayList...) } func (s *gatewaySet) Find(id ezkube.ResourceId) (*gateway_networking_k8s_io_v1beta1.Gateway, error) { @@ -233,7 +307,63 @@ func (s *gatewaySet) Clone() GatewaySet { if s == nil { return nil } - return &gatewaySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &gatewaySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *gatewaySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *gatewaySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type GatewayClassSet interface { @@ -271,30 +401,98 @@ type GatewayClassSet interface { Delta(newSet GatewayClassSet) sksets.ResourceDelta // Create a deep copy of the current GatewayClassSet Clone() GatewayClassSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericGatewayClassSet(gatewayClassList []*gateway_networking_k8s_io_v1beta1.GatewayClass) sksets.ResourceSet { +func makeGenericGatewayClassSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayClassList []*gateway_networking_k8s_io_v1beta1.GatewayClass, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range gatewayClassList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type gatewayClassSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewGatewayClassSet(gatewayClassList ...*gateway_networking_k8s_io_v1beta1.GatewayClass) GatewayClassSet { - return &gatewayClassSet{set: makeGenericGatewayClassSet(gatewayClassList)} +func NewGatewayClassSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayClassList ...*gateway_networking_k8s_io_v1beta1.GatewayClass, +) GatewayClassSet { + return &gatewayClassSet{ + set: makeGenericGatewayClassSet(sortFunc, equalityFunc, gatewayClassList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewGatewayClassSetFromList(gatewayClassList *gateway_networking_k8s_io_v1beta1.GatewayClassList) GatewayClassSet { +func NewGatewayClassSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + gatewayClassList *gateway_networking_k8s_io_v1beta1.GatewayClassList, +) GatewayClassSet { list := make([]*gateway_networking_k8s_io_v1beta1.GatewayClass, 0, len(gatewayClassList.Items)) for idx := range gatewayClassList.Items { list = append(list, &gatewayClassList.Items[idx]) } - return &gatewayClassSet{set: makeGenericGatewayClassSet(list)} + return &gatewayClassSet{ + set: makeGenericGatewayClassSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *gatewayClassSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *gatewayClassSet) Union(set GatewayClassSet) GatewayClassSet { if s == nil { return set } - return NewGatewayClassSet(append(s.List(), set.List()...)...) + return NewGatewayClassSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *gatewayClassSet) Difference(set GatewayClassSet) GatewayClassSet { @@ -402,7 +600,11 @@ func (s *gatewayClassSet) Difference(set GatewayClassSet) GatewayClassSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &gatewayClassSet{set: newSet} + return &gatewayClassSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *gatewayClassSet) Intersection(set GatewayClassSet) GatewayClassSet { @@ -414,7 +616,7 @@ func (s *gatewayClassSet) Intersection(set GatewayClassSet) GatewayClassSet { for _, obj := range newSet.List() { gatewayClassList = append(gatewayClassList, obj.(*gateway_networking_k8s_io_v1beta1.GatewayClass)) } - return NewGatewayClassSet(gatewayClassList...) + return NewGatewayClassSet(s.sortFunc, s.equalityFunc, gatewayClassList...) } func (s *gatewayClassSet) Find(id ezkube.ResourceId) (*gateway_networking_k8s_io_v1beta1.GatewayClass, error) { @@ -456,7 +658,63 @@ func (s *gatewayClassSet) Clone() GatewayClassSet { if s == nil { return nil } - return &gatewayClassSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.GatewayClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &gatewayClassSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *gatewayClassSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *gatewayClassSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type HTTPRouteSet interface { @@ -494,30 +752,98 @@ type HTTPRouteSet interface { Delta(newSet HTTPRouteSet) sksets.ResourceDelta // Create a deep copy of the current HTTPRouteSet Clone() HTTPRouteSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericHTTPRouteSet(hTTPRouteList []*gateway_networking_k8s_io_v1beta1.HTTPRoute) sksets.ResourceSet { +func makeGenericHTTPRouteSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteList []*gateway_networking_k8s_io_v1beta1.HTTPRoute, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range hTTPRouteList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type hTTPRouteSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewHTTPRouteSet(hTTPRouteList ...*gateway_networking_k8s_io_v1beta1.HTTPRoute) HTTPRouteSet { - return &hTTPRouteSet{set: makeGenericHTTPRouteSet(hTTPRouteList)} +func NewHTTPRouteSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteList ...*gateway_networking_k8s_io_v1beta1.HTTPRoute, +) HTTPRouteSet { + return &hTTPRouteSet{ + set: makeGenericHTTPRouteSet(sortFunc, equalityFunc, hTTPRouteList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewHTTPRouteSetFromList(hTTPRouteList *gateway_networking_k8s_io_v1beta1.HTTPRouteList) HTTPRouteSet { +func NewHTTPRouteSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteList *gateway_networking_k8s_io_v1beta1.HTTPRouteList, +) HTTPRouteSet { list := make([]*gateway_networking_k8s_io_v1beta1.HTTPRoute, 0, len(hTTPRouteList.Items)) for idx := range hTTPRouteList.Items { list = append(list, &hTTPRouteList.Items[idx]) } - return &hTTPRouteSet{set: makeGenericHTTPRouteSet(list)} + return &hTTPRouteSet{ + set: makeGenericHTTPRouteSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *hTTPRouteSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *hTTPRouteSet) Union(set HTTPRouteSet) HTTPRouteSet { if s == nil { return set } - return NewHTTPRouteSet(append(s.List(), set.List()...)...) + return NewHTTPRouteSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *hTTPRouteSet) Difference(set HTTPRouteSet) HTTPRouteSet { @@ -625,7 +951,11 @@ func (s *hTTPRouteSet) Difference(set HTTPRouteSet) HTTPRouteSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &hTTPRouteSet{set: newSet} + return &hTTPRouteSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *hTTPRouteSet) Intersection(set HTTPRouteSet) HTTPRouteSet { @@ -637,7 +967,7 @@ func (s *hTTPRouteSet) Intersection(set HTTPRouteSet) HTTPRouteSet { for _, obj := range newSet.List() { hTTPRouteList = append(hTTPRouteList, obj.(*gateway_networking_k8s_io_v1beta1.HTTPRoute)) } - return NewHTTPRouteSet(hTTPRouteList...) + return NewHTTPRouteSet(s.sortFunc, s.equalityFunc, hTTPRouteList...) } func (s *hTTPRouteSet) Find(id ezkube.ResourceId) (*gateway_networking_k8s_io_v1beta1.HTTPRoute, error) { @@ -679,5 +1009,61 @@ func (s *hTTPRouteSet) Clone() HTTPRouteSet { if s == nil { return nil } - return &hTTPRouteSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &gateway_networking_k8s_io_v1beta1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &hTTPRouteSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *hTTPRouteSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *hTTPRouteSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/networking.k8s.io/v1/sets/mocks/sets.go b/pkg/api/k8s/networking.k8s.io/v1/sets/mocks/sets.go index 30c447b..337c546 100644 --- a/pkg/api/k8s/networking.k8s.io/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/networking.k8s.io/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/networking/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockNetworkPolicySet is a mock of NetworkPolicySet interface. @@ -135,6 +136,34 @@ func (mr *MockNetworkPolicySetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockNetworkPolicySet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockNetworkPolicySet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockNetworkPolicySetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockNetworkPolicySet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockNetworkPolicySet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockNetworkPolicySetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockNetworkPolicySet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockNetworkPolicySet) Has(networkPolicy ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/networking.k8s.io/v1/sets/sets.go b/pkg/api/k8s/networking.k8s.io/v1/sets/sets.go index a81c45f..e603031 100644 --- a/pkg/api/k8s/networking.k8s.io/v1/sets/sets.go +++ b/pkg/api/k8s/networking.k8s.io/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type NetworkPolicySet interface { @@ -48,30 +50,98 @@ type NetworkPolicySet interface { Delta(newSet NetworkPolicySet) sksets.ResourceDelta // Create a deep copy of the current NetworkPolicySet Clone() NetworkPolicySet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericNetworkPolicySet(networkPolicyList []*networking_k8s_io_v1.NetworkPolicy) sksets.ResourceSet { +func makeGenericNetworkPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + networkPolicyList []*networking_k8s_io_v1.NetworkPolicy, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range networkPolicyList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type networkPolicySet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewNetworkPolicySet(networkPolicyList ...*networking_k8s_io_v1.NetworkPolicy) NetworkPolicySet { - return &networkPolicySet{set: makeGenericNetworkPolicySet(networkPolicyList)} +func NewNetworkPolicySet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + networkPolicyList ...*networking_k8s_io_v1.NetworkPolicy, +) NetworkPolicySet { + return &networkPolicySet{ + set: makeGenericNetworkPolicySet(sortFunc, equalityFunc, networkPolicyList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewNetworkPolicySetFromList(networkPolicyList *networking_k8s_io_v1.NetworkPolicyList) NetworkPolicySet { +func NewNetworkPolicySetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + networkPolicyList *networking_k8s_io_v1.NetworkPolicyList, +) NetworkPolicySet { list := make([]*networking_k8s_io_v1.NetworkPolicy, 0, len(networkPolicyList.Items)) for idx := range networkPolicyList.Items { list = append(list, &networkPolicyList.Items[idx]) } - return &networkPolicySet{set: makeGenericNetworkPolicySet(list)} + return &networkPolicySet{ + set: makeGenericNetworkPolicySet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *networkPolicySet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *networkPolicySet) Union(set NetworkPolicySet) NetworkPolicySet { if s == nil { return set } - return NewNetworkPolicySet(append(s.List(), set.List()...)...) + return NewNetworkPolicySet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *networkPolicySet) Difference(set NetworkPolicySet) NetworkPolicySet { @@ -179,7 +249,11 @@ func (s *networkPolicySet) Difference(set NetworkPolicySet) NetworkPolicySet { return set } newSet := s.Generic().Difference(set.Generic()) - return &networkPolicySet{set: newSet} + return &networkPolicySet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *networkPolicySet) Intersection(set NetworkPolicySet) NetworkPolicySet { @@ -191,7 +265,7 @@ func (s *networkPolicySet) Intersection(set NetworkPolicySet) NetworkPolicySet { for _, obj := range newSet.List() { networkPolicyList = append(networkPolicyList, obj.(*networking_k8s_io_v1.NetworkPolicy)) } - return NewNetworkPolicySet(networkPolicyList...) + return NewNetworkPolicySet(s.sortFunc, s.equalityFunc, networkPolicyList...) } func (s *networkPolicySet) Find(id ezkube.ResourceId) (*networking_k8s_io_v1.NetworkPolicy, error) { @@ -233,5 +307,61 @@ func (s *networkPolicySet) Clone() NetworkPolicySet { if s == nil { return nil } - return &networkPolicySet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &networking_k8s_io_v1.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &networkPolicySet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *networkPolicySet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *networkPolicySet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/mocks/sets.go b/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/mocks/sets.go index 298f8ef..c1c8010 100644 --- a/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/mocks/sets.go +++ b/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( ezkube "github.com/solo-io/skv2/pkg/ezkube" v1 "k8s.io/api/rbac/v1" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockRoleSet is a mock of RoleSet interface. @@ -135,6 +136,34 @@ func (mr *MockRoleSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockRoleSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockRoleSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockRoleSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockRoleSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockRoleSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockRoleSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockRoleSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockRoleSet) Has(role ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -391,6 +420,34 @@ func (mr *MockRoleBindingSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockRoleBindingSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockRoleBindingSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockRoleBindingSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockRoleBindingSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockRoleBindingSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockRoleBindingSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockRoleBindingSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockRoleBindingSet) Has(roleBinding ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -647,6 +704,34 @@ func (mr *MockClusterRoleSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockClusterRoleSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockClusterRoleSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockClusterRoleSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockClusterRoleSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockClusterRoleSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockClusterRoleSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockClusterRoleSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockClusterRoleSet) Has(clusterRole ezkube.ResourceId) bool { m.ctrl.T.Helper() @@ -903,6 +988,34 @@ func (mr *MockClusterRoleBindingSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockClusterRoleBindingSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockClusterRoleBindingSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockClusterRoleBindingSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockClusterRoleBindingSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockClusterRoleBindingSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockClusterRoleBindingSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockClusterRoleBindingSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockClusterRoleBindingSet) Has(clusterRoleBinding ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/sets.go b/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/sets.go index 4de18a8..c4c9a6e 100644 --- a/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/sets.go +++ b/pkg/api/k8s/rbac.authorization.k8s.io/v1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type RoleSet interface { @@ -48,30 +50,98 @@ type RoleSet interface { Delta(newSet RoleSet) sksets.ResourceDelta // Create a deep copy of the current RoleSet Clone() RoleSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericRoleSet(roleList []*rbac_authorization_k8s_io_v1.Role) sksets.ResourceSet { +func makeGenericRoleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleList []*rbac_authorization_k8s_io_v1.Role, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range roleList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type roleSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewRoleSet(roleList ...*rbac_authorization_k8s_io_v1.Role) RoleSet { - return &roleSet{set: makeGenericRoleSet(roleList)} +func NewRoleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleList ...*rbac_authorization_k8s_io_v1.Role, +) RoleSet { + return &roleSet{ + set: makeGenericRoleSet(sortFunc, equalityFunc, roleList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewRoleSetFromList(roleList *rbac_authorization_k8s_io_v1.RoleList) RoleSet { +func NewRoleSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleList *rbac_authorization_k8s_io_v1.RoleList, +) RoleSet { list := make([]*rbac_authorization_k8s_io_v1.Role, 0, len(roleList.Items)) for idx := range roleList.Items { list = append(list, &roleList.Items[idx]) } - return &roleSet{set: makeGenericRoleSet(list)} + return &roleSet{ + set: makeGenericRoleSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *roleSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *roleSet) Union(set RoleSet) RoleSet { if s == nil { return set } - return NewRoleSet(append(s.List(), set.List()...)...) + return NewRoleSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *roleSet) Difference(set RoleSet) RoleSet { @@ -179,7 +249,11 @@ func (s *roleSet) Difference(set RoleSet) RoleSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &roleSet{set: newSet} + return &roleSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *roleSet) Intersection(set RoleSet) RoleSet { @@ -191,7 +265,7 @@ func (s *roleSet) Intersection(set RoleSet) RoleSet { for _, obj := range newSet.List() { roleList = append(roleList, obj.(*rbac_authorization_k8s_io_v1.Role)) } - return NewRoleSet(roleList...) + return NewRoleSet(s.sortFunc, s.equalityFunc, roleList...) } func (s *roleSet) Find(id ezkube.ResourceId) (*rbac_authorization_k8s_io_v1.Role, error) { @@ -233,7 +307,63 @@ func (s *roleSet) Clone() RoleSet { if s == nil { return nil } - return &roleSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &roleSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *roleSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *roleSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type RoleBindingSet interface { @@ -271,30 +401,98 @@ type RoleBindingSet interface { Delta(newSet RoleBindingSet) sksets.ResourceDelta // Create a deep copy of the current RoleBindingSet Clone() RoleBindingSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericRoleBindingSet(roleBindingList []*rbac_authorization_k8s_io_v1.RoleBinding) sksets.ResourceSet { +func makeGenericRoleBindingSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleBindingList []*rbac_authorization_k8s_io_v1.RoleBinding, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range roleBindingList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type roleBindingSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewRoleBindingSet(roleBindingList ...*rbac_authorization_k8s_io_v1.RoleBinding) RoleBindingSet { - return &roleBindingSet{set: makeGenericRoleBindingSet(roleBindingList)} +func NewRoleBindingSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleBindingList ...*rbac_authorization_k8s_io_v1.RoleBinding, +) RoleBindingSet { + return &roleBindingSet{ + set: makeGenericRoleBindingSet(sortFunc, equalityFunc, roleBindingList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewRoleBindingSetFromList(roleBindingList *rbac_authorization_k8s_io_v1.RoleBindingList) RoleBindingSet { +func NewRoleBindingSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + roleBindingList *rbac_authorization_k8s_io_v1.RoleBindingList, +) RoleBindingSet { list := make([]*rbac_authorization_k8s_io_v1.RoleBinding, 0, len(roleBindingList.Items)) for idx := range roleBindingList.Items { list = append(list, &roleBindingList.Items[idx]) } - return &roleBindingSet{set: makeGenericRoleBindingSet(list)} + return &roleBindingSet{ + set: makeGenericRoleBindingSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *roleBindingSet) Keys() sets.String { @@ -394,7 +592,7 @@ func (s *roleBindingSet) Union(set RoleBindingSet) RoleBindingSet { if s == nil { return set } - return NewRoleBindingSet(append(s.List(), set.List()...)...) + return NewRoleBindingSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *roleBindingSet) Difference(set RoleBindingSet) RoleBindingSet { @@ -402,7 +600,11 @@ func (s *roleBindingSet) Difference(set RoleBindingSet) RoleBindingSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &roleBindingSet{set: newSet} + return &roleBindingSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *roleBindingSet) Intersection(set RoleBindingSet) RoleBindingSet { @@ -414,7 +616,7 @@ func (s *roleBindingSet) Intersection(set RoleBindingSet) RoleBindingSet { for _, obj := range newSet.List() { roleBindingList = append(roleBindingList, obj.(*rbac_authorization_k8s_io_v1.RoleBinding)) } - return NewRoleBindingSet(roleBindingList...) + return NewRoleBindingSet(s.sortFunc, s.equalityFunc, roleBindingList...) } func (s *roleBindingSet) Find(id ezkube.ResourceId) (*rbac_authorization_k8s_io_v1.RoleBinding, error) { @@ -456,7 +658,63 @@ func (s *roleBindingSet) Clone() RoleBindingSet { if s == nil { return nil } - return &roleBindingSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &roleBindingSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *roleBindingSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *roleBindingSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ClusterRoleSet interface { @@ -494,30 +752,98 @@ type ClusterRoleSet interface { Delta(newSet ClusterRoleSet) sksets.ResourceDelta // Create a deep copy of the current ClusterRoleSet Clone() ClusterRoleSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericClusterRoleSet(clusterRoleList []*rbac_authorization_k8s_io_v1.ClusterRole) sksets.ResourceSet { +func makeGenericClusterRoleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleList []*rbac_authorization_k8s_io_v1.ClusterRole, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range clusterRoleList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type clusterRoleSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewClusterRoleSet(clusterRoleList ...*rbac_authorization_k8s_io_v1.ClusterRole) ClusterRoleSet { - return &clusterRoleSet{set: makeGenericClusterRoleSet(clusterRoleList)} +func NewClusterRoleSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleList ...*rbac_authorization_k8s_io_v1.ClusterRole, +) ClusterRoleSet { + return &clusterRoleSet{ + set: makeGenericClusterRoleSet(sortFunc, equalityFunc, clusterRoleList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewClusterRoleSetFromList(clusterRoleList *rbac_authorization_k8s_io_v1.ClusterRoleList) ClusterRoleSet { +func NewClusterRoleSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleList *rbac_authorization_k8s_io_v1.ClusterRoleList, +) ClusterRoleSet { list := make([]*rbac_authorization_k8s_io_v1.ClusterRole, 0, len(clusterRoleList.Items)) for idx := range clusterRoleList.Items { list = append(list, &clusterRoleList.Items[idx]) } - return &clusterRoleSet{set: makeGenericClusterRoleSet(list)} + return &clusterRoleSet{ + set: makeGenericClusterRoleSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *clusterRoleSet) Keys() sets.String { @@ -617,7 +943,7 @@ func (s *clusterRoleSet) Union(set ClusterRoleSet) ClusterRoleSet { if s == nil { return set } - return NewClusterRoleSet(append(s.List(), set.List()...)...) + return NewClusterRoleSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *clusterRoleSet) Difference(set ClusterRoleSet) ClusterRoleSet { @@ -625,7 +951,11 @@ func (s *clusterRoleSet) Difference(set ClusterRoleSet) ClusterRoleSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &clusterRoleSet{set: newSet} + return &clusterRoleSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *clusterRoleSet) Intersection(set ClusterRoleSet) ClusterRoleSet { @@ -637,7 +967,7 @@ func (s *clusterRoleSet) Intersection(set ClusterRoleSet) ClusterRoleSet { for _, obj := range newSet.List() { clusterRoleList = append(clusterRoleList, obj.(*rbac_authorization_k8s_io_v1.ClusterRole)) } - return NewClusterRoleSet(clusterRoleList...) + return NewClusterRoleSet(s.sortFunc, s.equalityFunc, clusterRoleList...) } func (s *clusterRoleSet) Find(id ezkube.ResourceId) (*rbac_authorization_k8s_io_v1.ClusterRole, error) { @@ -679,7 +1009,63 @@ func (s *clusterRoleSet) Clone() ClusterRoleSet { if s == nil { return nil } - return &clusterRoleSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &clusterRoleSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *clusterRoleSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *clusterRoleSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } type ClusterRoleBindingSet interface { @@ -717,30 +1103,98 @@ type ClusterRoleBindingSet interface { Delta(newSet ClusterRoleBindingSet) sksets.ResourceDelta // Create a deep copy of the current ClusterRoleBindingSet Clone() ClusterRoleBindingSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericClusterRoleBindingSet(clusterRoleBindingList []*rbac_authorization_k8s_io_v1.ClusterRoleBinding) sksets.ResourceSet { +func makeGenericClusterRoleBindingSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleBindingList []*rbac_authorization_k8s_io_v1.ClusterRoleBinding, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range clusterRoleBindingList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type clusterRoleBindingSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewClusterRoleBindingSet(clusterRoleBindingList ...*rbac_authorization_k8s_io_v1.ClusterRoleBinding) ClusterRoleBindingSet { - return &clusterRoleBindingSet{set: makeGenericClusterRoleBindingSet(clusterRoleBindingList)} +func NewClusterRoleBindingSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleBindingList ...*rbac_authorization_k8s_io_v1.ClusterRoleBinding, +) ClusterRoleBindingSet { + return &clusterRoleBindingSet{ + set: makeGenericClusterRoleBindingSet(sortFunc, equalityFunc, clusterRoleBindingList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewClusterRoleBindingSetFromList(clusterRoleBindingList *rbac_authorization_k8s_io_v1.ClusterRoleBindingList) ClusterRoleBindingSet { +func NewClusterRoleBindingSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + clusterRoleBindingList *rbac_authorization_k8s_io_v1.ClusterRoleBindingList, +) ClusterRoleBindingSet { list := make([]*rbac_authorization_k8s_io_v1.ClusterRoleBinding, 0, len(clusterRoleBindingList.Items)) for idx := range clusterRoleBindingList.Items { list = append(list, &clusterRoleBindingList.Items[idx]) } - return &clusterRoleBindingSet{set: makeGenericClusterRoleBindingSet(list)} + return &clusterRoleBindingSet{ + set: makeGenericClusterRoleBindingSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *clusterRoleBindingSet) Keys() sets.String { @@ -840,7 +1294,7 @@ func (s *clusterRoleBindingSet) Union(set ClusterRoleBindingSet) ClusterRoleBind if s == nil { return set } - return NewClusterRoleBindingSet(append(s.List(), set.List()...)...) + return NewClusterRoleBindingSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *clusterRoleBindingSet) Difference(set ClusterRoleBindingSet) ClusterRoleBindingSet { @@ -848,7 +1302,11 @@ func (s *clusterRoleBindingSet) Difference(set ClusterRoleBindingSet) ClusterRol return set } newSet := s.Generic().Difference(set.Generic()) - return &clusterRoleBindingSet{set: newSet} + return &clusterRoleBindingSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *clusterRoleBindingSet) Intersection(set ClusterRoleBindingSet) ClusterRoleBindingSet { @@ -860,7 +1318,7 @@ func (s *clusterRoleBindingSet) Intersection(set ClusterRoleBindingSet) ClusterR for _, obj := range newSet.List() { clusterRoleBindingList = append(clusterRoleBindingList, obj.(*rbac_authorization_k8s_io_v1.ClusterRoleBinding)) } - return NewClusterRoleBindingSet(clusterRoleBindingList...) + return NewClusterRoleBindingSet(s.sortFunc, s.equalityFunc, clusterRoleBindingList...) } func (s *clusterRoleBindingSet) Find(id ezkube.ResourceId) (*rbac_authorization_k8s_io_v1.ClusterRoleBinding, error) { @@ -902,5 +1360,61 @@ func (s *clusterRoleBindingSet) Clone() ClusterRoleBindingSet { if s == nil { return nil } - return &clusterRoleBindingSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &rbac_authorization_k8s_io_v1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &clusterRoleBindingSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *clusterRoleBindingSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *clusterRoleBindingSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/mocks/sets.go b/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/mocks/sets.go index 53f6736..58fb6cc 100644 --- a/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/mocks/sets.go +++ b/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockTrafficTargetSet is a mock of TrafficTargetSet interface. @@ -135,6 +136,34 @@ func (mr *MockTrafficTargetSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockTrafficTargetSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockTrafficTargetSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockTrafficTargetSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockTrafficTargetSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockTrafficTargetSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockTrafficTargetSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockTrafficTargetSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockTrafficTargetSet) Has(trafficTarget ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/sets.go b/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/sets.go index 50716c8..336da82 100644 --- a/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/sets.go +++ b/pkg/api/smi/access.smi-spec.io/v1alpha2/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type TrafficTargetSet interface { @@ -48,30 +50,98 @@ type TrafficTargetSet interface { Delta(newSet TrafficTargetSet) sksets.ResourceDelta // Create a deep copy of the current TrafficTargetSet Clone() TrafficTargetSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericTrafficTargetSet(trafficTargetList []*access_smi_spec_io_v1alpha2.TrafficTarget) sksets.ResourceSet { +func makeGenericTrafficTargetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficTargetList []*access_smi_spec_io_v1alpha2.TrafficTarget, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range trafficTargetList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type trafficTargetSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewTrafficTargetSet(trafficTargetList ...*access_smi_spec_io_v1alpha2.TrafficTarget) TrafficTargetSet { - return &trafficTargetSet{set: makeGenericTrafficTargetSet(trafficTargetList)} +func NewTrafficTargetSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficTargetList ...*access_smi_spec_io_v1alpha2.TrafficTarget, +) TrafficTargetSet { + return &trafficTargetSet{ + set: makeGenericTrafficTargetSet(sortFunc, equalityFunc, trafficTargetList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewTrafficTargetSetFromList(trafficTargetList *access_smi_spec_io_v1alpha2.TrafficTargetList) TrafficTargetSet { +func NewTrafficTargetSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficTargetList *access_smi_spec_io_v1alpha2.TrafficTargetList, +) TrafficTargetSet { list := make([]*access_smi_spec_io_v1alpha2.TrafficTarget, 0, len(trafficTargetList.Items)) for idx := range trafficTargetList.Items { list = append(list, &trafficTargetList.Items[idx]) } - return &trafficTargetSet{set: makeGenericTrafficTargetSet(list)} + return &trafficTargetSet{ + set: makeGenericTrafficTargetSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *trafficTargetSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *trafficTargetSet) Union(set TrafficTargetSet) TrafficTargetSet { if s == nil { return set } - return NewTrafficTargetSet(append(s.List(), set.List()...)...) + return NewTrafficTargetSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *trafficTargetSet) Difference(set TrafficTargetSet) TrafficTargetSet { @@ -179,7 +249,11 @@ func (s *trafficTargetSet) Difference(set TrafficTargetSet) TrafficTargetSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &trafficTargetSet{set: newSet} + return &trafficTargetSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *trafficTargetSet) Intersection(set TrafficTargetSet) TrafficTargetSet { @@ -191,7 +265,7 @@ func (s *trafficTargetSet) Intersection(set TrafficTargetSet) TrafficTargetSet { for _, obj := range newSet.List() { trafficTargetList = append(trafficTargetList, obj.(*access_smi_spec_io_v1alpha2.TrafficTarget)) } - return NewTrafficTargetSet(trafficTargetList...) + return NewTrafficTargetSet(s.sortFunc, s.equalityFunc, trafficTargetList...) } func (s *trafficTargetSet) Find(id ezkube.ResourceId) (*access_smi_spec_io_v1alpha2.TrafficTarget, error) { @@ -233,5 +307,61 @@ func (s *trafficTargetSet) Clone() TrafficTargetSet { if s == nil { return nil } - return &trafficTargetSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &access_smi_spec_io_v1alpha2.TrafficTarget{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &trafficTargetSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *trafficTargetSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *trafficTargetSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/mocks/sets.go b/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/mocks/sets.go index fcacd61..d236457 100644 --- a/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/mocks/sets.go +++ b/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockHTTPRouteGroupSet is a mock of HTTPRouteGroupSet interface. @@ -135,6 +136,34 @@ func (mr *MockHTTPRouteGroupSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockHTTPRouteGroupSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockHTTPRouteGroupSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockHTTPRouteGroupSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockHTTPRouteGroupSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockHTTPRouteGroupSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockHTTPRouteGroupSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockHTTPRouteGroupSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockHTTPRouteGroupSet) Has(hTTPRouteGroup ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/sets.go b/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/sets.go index 2e3903c..bef47bd 100644 --- a/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/sets.go +++ b/pkg/api/smi/specs.smi-spec.io/v1alpha3/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type HTTPRouteGroupSet interface { @@ -48,30 +50,98 @@ type HTTPRouteGroupSet interface { Delta(newSet HTTPRouteGroupSet) sksets.ResourceDelta // Create a deep copy of the current HTTPRouteGroupSet Clone() HTTPRouteGroupSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericHTTPRouteGroupSet(hTTPRouteGroupList []*specs_smi_spec_io_v1alpha3.HTTPRouteGroup) sksets.ResourceSet { +func makeGenericHTTPRouteGroupSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteGroupList []*specs_smi_spec_io_v1alpha3.HTTPRouteGroup, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range hTTPRouteGroupList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type hTTPRouteGroupSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewHTTPRouteGroupSet(hTTPRouteGroupList ...*specs_smi_spec_io_v1alpha3.HTTPRouteGroup) HTTPRouteGroupSet { - return &hTTPRouteGroupSet{set: makeGenericHTTPRouteGroupSet(hTTPRouteGroupList)} +func NewHTTPRouteGroupSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteGroupList ...*specs_smi_spec_io_v1alpha3.HTTPRouteGroup, +) HTTPRouteGroupSet { + return &hTTPRouteGroupSet{ + set: makeGenericHTTPRouteGroupSet(sortFunc, equalityFunc, hTTPRouteGroupList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewHTTPRouteGroupSetFromList(hTTPRouteGroupList *specs_smi_spec_io_v1alpha3.HTTPRouteGroupList) HTTPRouteGroupSet { +func NewHTTPRouteGroupSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + hTTPRouteGroupList *specs_smi_spec_io_v1alpha3.HTTPRouteGroupList, +) HTTPRouteGroupSet { list := make([]*specs_smi_spec_io_v1alpha3.HTTPRouteGroup, 0, len(hTTPRouteGroupList.Items)) for idx := range hTTPRouteGroupList.Items { list = append(list, &hTTPRouteGroupList.Items[idx]) } - return &hTTPRouteGroupSet{set: makeGenericHTTPRouteGroupSet(list)} + return &hTTPRouteGroupSet{ + set: makeGenericHTTPRouteGroupSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *hTTPRouteGroupSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *hTTPRouteGroupSet) Union(set HTTPRouteGroupSet) HTTPRouteGroupSet { if s == nil { return set } - return NewHTTPRouteGroupSet(append(s.List(), set.List()...)...) + return NewHTTPRouteGroupSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *hTTPRouteGroupSet) Difference(set HTTPRouteGroupSet) HTTPRouteGroupSet { @@ -179,7 +249,11 @@ func (s *hTTPRouteGroupSet) Difference(set HTTPRouteGroupSet) HTTPRouteGroupSet return set } newSet := s.Generic().Difference(set.Generic()) - return &hTTPRouteGroupSet{set: newSet} + return &hTTPRouteGroupSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *hTTPRouteGroupSet) Intersection(set HTTPRouteGroupSet) HTTPRouteGroupSet { @@ -191,7 +265,7 @@ func (s *hTTPRouteGroupSet) Intersection(set HTTPRouteGroupSet) HTTPRouteGroupSe for _, obj := range newSet.List() { hTTPRouteGroupList = append(hTTPRouteGroupList, obj.(*specs_smi_spec_io_v1alpha3.HTTPRouteGroup)) } - return NewHTTPRouteGroupSet(hTTPRouteGroupList...) + return NewHTTPRouteGroupSet(s.sortFunc, s.equalityFunc, hTTPRouteGroupList...) } func (s *hTTPRouteGroupSet) Find(id ezkube.ResourceId) (*specs_smi_spec_io_v1alpha3.HTTPRouteGroup, error) { @@ -233,5 +307,61 @@ func (s *hTTPRouteGroupSet) Clone() HTTPRouteGroupSet { if s == nil { return nil } - return &hTTPRouteGroupSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &specs_smi_spec_io_v1alpha3.HTTPRouteGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &hTTPRouteGroupSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *hTTPRouteGroupSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *hTTPRouteGroupSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/mocks/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/mocks/sets.go index 4bc918f..b0f4f4a 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/mocks/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockTrafficSplitSet is a mock of TrafficSplitSet interface. @@ -135,6 +136,34 @@ func (mr *MockTrafficSplitSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockTrafficSplitSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockTrafficSplitSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockTrafficSplitSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockTrafficSplitSet) Has(trafficSplit ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/sets.go index 04a4a44..b42a4be 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha1/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type TrafficSplitSet interface { @@ -48,30 +50,98 @@ type TrafficSplitSet interface { Delta(newSet TrafficSplitSet) sksets.ResourceDelta // Create a deep copy of the current TrafficSplitSet Clone() TrafficSplitSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericTrafficSplitSet(trafficSplitList []*split_smi_spec_io_v1alpha1.TrafficSplit) sksets.ResourceSet { +func makeGenericTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList []*split_smi_spec_io_v1alpha1.TrafficSplit, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range trafficSplitList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type trafficSplitSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewTrafficSplitSet(trafficSplitList ...*split_smi_spec_io_v1alpha1.TrafficSplit) TrafficSplitSet { - return &trafficSplitSet{set: makeGenericTrafficSplitSet(trafficSplitList)} +func NewTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList ...*split_smi_spec_io_v1alpha1.TrafficSplit, +) TrafficSplitSet { + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, trafficSplitList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewTrafficSplitSetFromList(trafficSplitList *split_smi_spec_io_v1alpha1.TrafficSplitList) TrafficSplitSet { +func NewTrafficSplitSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList *split_smi_spec_io_v1alpha1.TrafficSplitList, +) TrafficSplitSet { list := make([]*split_smi_spec_io_v1alpha1.TrafficSplit, 0, len(trafficSplitList.Items)) for idx := range trafficSplitList.Items { list = append(list, &trafficSplitList.Items[idx]) } - return &trafficSplitSet{set: makeGenericTrafficSplitSet(list)} + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *trafficSplitSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *trafficSplitSet) Union(set TrafficSplitSet) TrafficSplitSet { if s == nil { return set } - return NewTrafficSplitSet(append(s.List(), set.List()...)...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { @@ -179,7 +249,11 @@ func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &trafficSplitSet{set: newSet} + return &trafficSplitSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { @@ -191,7 +265,7 @@ func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { for _, obj := range newSet.List() { trafficSplitList = append(trafficSplitList, obj.(*split_smi_spec_io_v1alpha1.TrafficSplit)) } - return NewTrafficSplitSet(trafficSplitList...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, trafficSplitList...) } func (s *trafficSplitSet) Find(id ezkube.ResourceId) (*split_smi_spec_io_v1alpha1.TrafficSplit, error) { @@ -233,5 +307,61 @@ func (s *trafficSplitSet) Clone() TrafficSplitSet { if s == nil { return nil } - return &trafficSplitSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha1.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &trafficSplitSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *trafficSplitSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *trafficSplitSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/mocks/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/mocks/sets.go index f21ff0f..ad754cc 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/mocks/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockTrafficSplitSet is a mock of TrafficSplitSet interface. @@ -135,6 +136,34 @@ func (mr *MockTrafficSplitSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockTrafficSplitSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockTrafficSplitSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockTrafficSplitSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockTrafficSplitSet) Has(trafficSplit ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/sets.go index a521553..b679ec4 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha2/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type TrafficSplitSet interface { @@ -48,30 +50,98 @@ type TrafficSplitSet interface { Delta(newSet TrafficSplitSet) sksets.ResourceDelta // Create a deep copy of the current TrafficSplitSet Clone() TrafficSplitSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericTrafficSplitSet(trafficSplitList []*split_smi_spec_io_v1alpha2.TrafficSplit) sksets.ResourceSet { +func makeGenericTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList []*split_smi_spec_io_v1alpha2.TrafficSplit, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range trafficSplitList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type trafficSplitSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewTrafficSplitSet(trafficSplitList ...*split_smi_spec_io_v1alpha2.TrafficSplit) TrafficSplitSet { - return &trafficSplitSet{set: makeGenericTrafficSplitSet(trafficSplitList)} +func NewTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList ...*split_smi_spec_io_v1alpha2.TrafficSplit, +) TrafficSplitSet { + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, trafficSplitList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewTrafficSplitSetFromList(trafficSplitList *split_smi_spec_io_v1alpha2.TrafficSplitList) TrafficSplitSet { +func NewTrafficSplitSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList *split_smi_spec_io_v1alpha2.TrafficSplitList, +) TrafficSplitSet { list := make([]*split_smi_spec_io_v1alpha2.TrafficSplit, 0, len(trafficSplitList.Items)) for idx := range trafficSplitList.Items { list = append(list, &trafficSplitList.Items[idx]) } - return &trafficSplitSet{set: makeGenericTrafficSplitSet(list)} + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *trafficSplitSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *trafficSplitSet) Union(set TrafficSplitSet) TrafficSplitSet { if s == nil { return set } - return NewTrafficSplitSet(append(s.List(), set.List()...)...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { @@ -179,7 +249,11 @@ func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &trafficSplitSet{set: newSet} + return &trafficSplitSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { @@ -191,7 +265,7 @@ func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { for _, obj := range newSet.List() { trafficSplitList = append(trafficSplitList, obj.(*split_smi_spec_io_v1alpha2.TrafficSplit)) } - return NewTrafficSplitSet(trafficSplitList...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, trafficSplitList...) } func (s *trafficSplitSet) Find(id ezkube.ResourceId) (*split_smi_spec_io_v1alpha2.TrafficSplit, error) { @@ -233,5 +307,61 @@ func (s *trafficSplitSet) Clone() TrafficSplitSet { if s == nil { return nil } - return &trafficSplitSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha2.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &trafficSplitSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *trafficSplitSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *trafficSplitSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc } diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/mocks/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/mocks/sets.go index 061c5b5..137bba3 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/mocks/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/mocks/sets.go @@ -13,6 +13,7 @@ import ( sets "github.com/solo-io/skv2/contrib/pkg/sets" ezkube "github.com/solo-io/skv2/pkg/ezkube" sets0 "k8s.io/apimachinery/pkg/util/sets" + client "sigs.k8s.io/controller-runtime/pkg/client" ) // MockTrafficSplitSet is a mock of TrafficSplitSet interface. @@ -135,6 +136,34 @@ func (mr *MockTrafficSplitSetMockRecorder) Generic() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Generic", reflect.TypeOf((*MockTrafficSplitSet)(nil).Generic)) } +// GetEqualityFunc mocks base method. +func (m *MockTrafficSplitSet) GetEqualityFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEqualityFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetEqualityFunc indicates an expected call of GetEqualityFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetEqualityFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEqualityFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetEqualityFunc)) +} + +// GetSortFunc mocks base method. +func (m *MockTrafficSplitSet) GetSortFunc() func(client.Object, client.Object) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSortFunc") + ret0, _ := ret[0].(func(client.Object, client.Object) bool) + return ret0 +} + +// GetSortFunc indicates an expected call of GetSortFunc. +func (mr *MockTrafficSplitSetMockRecorder) GetSortFunc() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSortFunc", reflect.TypeOf((*MockTrafficSplitSet)(nil).GetSortFunc)) +} + // Has mocks base method. func (m *MockTrafficSplitSet) Has(trafficSplit ezkube.ResourceId) bool { m.ctrl.T.Helper() diff --git a/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/sets.go b/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/sets.go index d4e789e..a60a532 100644 --- a/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/sets.go +++ b/pkg/api/smi/split.smi-spec.io/v1alpha3/sets/sets.go @@ -10,7 +10,9 @@ import ( "github.com/rotisserie/eris" sksets "github.com/solo-io/skv2/contrib/pkg/sets" "github.com/solo-io/skv2/pkg/ezkube" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/client" ) type TrafficSplitSet interface { @@ -48,30 +50,98 @@ type TrafficSplitSet interface { Delta(newSet TrafficSplitSet) sksets.ResourceDelta // Create a deep copy of the current TrafficSplitSet Clone() TrafficSplitSet + // Get the sort function used by the set + GetSortFunc() func(toInsert, existing client.Object) bool + // Get the equality function used by the set + GetEqualityFunc() func(a, b client.Object) bool } -func makeGenericTrafficSplitSet(trafficSplitList []*split_smi_spec_io_v1alpha3.TrafficSplit) sksets.ResourceSet { +func makeGenericTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList []*split_smi_spec_io_v1alpha3.TrafficSplit, +) sksets.ResourceSet { var genericResources []ezkube.ResourceId for _, obj := range trafficSplitList { genericResources = append(genericResources, obj) } - return sksets.NewResourceSet(genericResources...) + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return equalityFunc(objA, objB) + } + return sksets.NewResourceSet(genericSortFunc, genericEqualityFunc, genericResources...) } type trafficSplitSet struct { - set sksets.ResourceSet + set sksets.ResourceSet + sortFunc func(toInsert, existing client.Object) bool + equalityFunc func(a, b client.Object) bool } -func NewTrafficSplitSet(trafficSplitList ...*split_smi_spec_io_v1alpha3.TrafficSplit) TrafficSplitSet { - return &trafficSplitSet{set: makeGenericTrafficSplitSet(trafficSplitList)} +func NewTrafficSplitSet( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList ...*split_smi_spec_io_v1alpha3.TrafficSplit, +) TrafficSplitSet { + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, trafficSplitList), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } -func NewTrafficSplitSetFromList(trafficSplitList *split_smi_spec_io_v1alpha3.TrafficSplitList) TrafficSplitSet { +func NewTrafficSplitSetFromList( + sortFunc func(toInsert, existing client.Object) bool, + equalityFunc func(a, b client.Object) bool, + trafficSplitList *split_smi_spec_io_v1alpha3.TrafficSplitList, +) TrafficSplitSet { list := make([]*split_smi_spec_io_v1alpha3.TrafficSplit, 0, len(trafficSplitList.Items)) for idx := range trafficSplitList.Items { list = append(list, &trafficSplitList.Items[idx]) } - return &trafficSplitSet{set: makeGenericTrafficSplitSet(list)} + return &trafficSplitSet{ + set: makeGenericTrafficSplitSet(sortFunc, equalityFunc, list), + sortFunc: sortFunc, + equalityFunc: equalityFunc, + } } func (s *trafficSplitSet) Keys() sets.String { @@ -171,7 +241,7 @@ func (s *trafficSplitSet) Union(set TrafficSplitSet) TrafficSplitSet { if s == nil { return set } - return NewTrafficSplitSet(append(s.List(), set.List()...)...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, append(s.List(), set.List()...)...) } func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { @@ -179,7 +249,11 @@ func (s *trafficSplitSet) Difference(set TrafficSplitSet) TrafficSplitSet { return set } newSet := s.Generic().Difference(set.Generic()) - return &trafficSplitSet{set: newSet} + return &trafficSplitSet{ + set: newSet, + sortFunc: s.sortFunc, + equalityFunc: s.equalityFunc, + } } func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { @@ -191,7 +265,7 @@ func (s *trafficSplitSet) Intersection(set TrafficSplitSet) TrafficSplitSet { for _, obj := range newSet.List() { trafficSplitList = append(trafficSplitList, obj.(*split_smi_spec_io_v1alpha3.TrafficSplit)) } - return NewTrafficSplitSet(trafficSplitList...) + return NewTrafficSplitSet(s.sortFunc, s.equalityFunc, trafficSplitList...) } func (s *trafficSplitSet) Find(id ezkube.ResourceId) (*split_smi_spec_io_v1alpha3.TrafficSplit, error) { @@ -233,5 +307,61 @@ func (s *trafficSplitSet) Clone() TrafficSplitSet { if s == nil { return nil } - return &trafficSplitSet{set: sksets.NewResourceSet(s.Generic().Clone().List()...)} + genericSortFunc := func(toInsert, existing ezkube.ResourceId) bool { + objToInsert, ok := toInsert.(client.Object) + if !ok { + objToInsert = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: toInsert.GetName(), + Namespace: toInsert.GetNamespace(), + }, + } + } + objExisting, ok := existing.(client.Object) + if !ok { + objExisting = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: existing.GetName(), + Namespace: existing.GetNamespace(), + }, + } + } + return s.sortFunc(objToInsert, objExisting) + } + genericEqualityFunc := func(a, b ezkube.ResourceId) bool { + objA, ok := a.(client.Object) + if !ok { + objA = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: a.GetName(), + Namespace: a.GetNamespace(), + }, + } + } + objB, ok := b.(client.Object) + if !ok { + objB = &split_smi_spec_io_v1alpha3.TrafficSplit{ + ObjectMeta: metav1.ObjectMeta{ + Name: b.GetName(), + Namespace: b.GetNamespace(), + }, + } + } + return s.equalityFunc(objA, objB) + } + return &trafficSplitSet{ + set: sksets.NewResourceSet( + genericSortFunc, + genericEqualityFunc, + s.Generic().Clone().List()..., + ), + } +} + +func (s *trafficSplitSet) GetSortFunc() func(toInsert, existing client.Object) bool { + return s.sortFunc +} + +func (s *trafficSplitSet) GetEqualityFunc() func(a, b client.Object) bool { + return s.equalityFunc }