@@ -21,13 +21,17 @@ import (
2121
2222 rbacv1 "k8s.io/api/rbac/v1"
2323 "k8s.io/apimachinery/pkg/api/equality"
24+ "k8s.io/apimachinery/pkg/api/errors"
2425 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526 "k8s.io/apimachinery/pkg/runtime"
2627 "k8s.io/apimachinery/pkg/util/diff"
28+ "k8s.io/apimachinery/pkg/util/yaml"
29+ rbacv1ac "k8s.io/client-go/applyconfigurations/rbac/v1"
2730 fakeclient "k8s.io/client-go/kubernetes/fake"
2831 rbaclisters "k8s.io/client-go/listers/rbac/v1"
2932 clienttesting "k8s.io/client-go/testing"
3033 "k8s.io/client-go/tools/cache"
34+
3135 "k8s.io/kubernetes/pkg/controller"
3236)
3337
@@ -69,29 +73,43 @@ func TestSyncClusterRole(t *testing.T) {
6973 return ret
7074 }
7175
76+ combinedApplyRole := func (selectors []map [string ]string , rules ... []rbacv1.PolicyRule ) * rbacv1ac.ClusterRoleApplyConfiguration {
77+ ret := rbacv1ac .ClusterRole ("combined" )
78+
79+ var r []* rbacv1ac.PolicyRuleApplyConfiguration
80+ for _ , currRules := range rules {
81+ r = append (r , toApplyPolicyRules (currRules )... )
82+ }
83+ ret .WithRules (r ... )
84+ return ret
85+ }
86+
7287 tests := []struct {
73- name string
74- startingClusterRoles []* rbacv1.ClusterRole
75- clusterRoleToSync string
76- expectedClusterRole * rbacv1.ClusterRole
88+ name string
89+ startingClusterRoles []* rbacv1.ClusterRole
90+ clusterRoleToSync string
91+ expectedClusterRole * rbacv1.ClusterRole
92+ expectedClusterRoleApply * rbacv1ac.ClusterRoleApplyConfiguration
7793 }{
7894 {
7995 name : "remove dead rules" ,
8096 startingClusterRoles : []* rbacv1.ClusterRole {
8197 role ("hammer" , map [string ]string {"foo" : "bar" }, hammerRules ()),
8298 combinedRole ([]map [string ]string {{"foo" : "bar" }}, sawRules ()),
8399 },
84- clusterRoleToSync : "combined" ,
85- expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}, hammerRules ()),
100+ clusterRoleToSync : "combined" ,
101+ expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}, hammerRules ()),
102+ expectedClusterRoleApply : combinedApplyRole ([]map [string ]string {{"foo" : "bar" }}, hammerRules ()),
86103 },
87104 {
88105 name : "strip rules" ,
89106 startingClusterRoles : []* rbacv1.ClusterRole {
90107 role ("hammer" , map [string ]string {"foo" : "not-bar" }, hammerRules ()),
91108 combinedRole ([]map [string ]string {{"foo" : "bar" }}, hammerRules ()),
92109 },
93- clusterRoleToSync : "combined" ,
94- expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}),
110+ clusterRoleToSync : "combined" ,
111+ expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}),
112+ expectedClusterRoleApply : combinedApplyRole ([]map [string ]string {{"foo" : "bar" }}),
95113 },
96114 {
97115 name : "select properly and put in order" ,
@@ -101,8 +119,9 @@ func TestSyncClusterRole(t *testing.T) {
101119 role ("saw" , map [string ]string {"foo" : "not-bar" }, sawRules ()),
102120 combinedRole ([]map [string ]string {{"foo" : "bar" }}),
103121 },
104- clusterRoleToSync : "combined" ,
105- expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}, chiselRules (), hammerRules ()),
122+ clusterRoleToSync : "combined" ,
123+ expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }}, chiselRules (), hammerRules ()),
124+ expectedClusterRoleApply : combinedApplyRole ([]map [string ]string {{"foo" : "bar" }}, chiselRules (), hammerRules ()),
106125 },
107126 {
108127 name : "select properly with multiple selectors" ,
@@ -112,8 +131,9 @@ func TestSyncClusterRole(t *testing.T) {
112131 role ("saw" , map [string ]string {"foo" : "not-bar" }, sawRules ()),
113132 combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}),
114133 },
115- clusterRoleToSync : "combined" ,
116- expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
134+ clusterRoleToSync : "combined" ,
135+ expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
136+ expectedClusterRoleApply : combinedApplyRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
117137 },
118138 {
119139 name : "select properly remove duplicates" ,
@@ -124,59 +144,92 @@ func TestSyncClusterRole(t *testing.T) {
124144 role ("other-saw" , map [string ]string {"foo" : "not-bar" }, sawRules ()),
125145 combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}),
126146 },
127- clusterRoleToSync : "combined" ,
128- expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
147+ clusterRoleToSync : "combined" ,
148+ expectedClusterRole : combinedRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
149+ expectedClusterRoleApply : combinedApplyRole ([]map [string ]string {{"foo" : "bar" }, {"foo" : "not-bar" }}, chiselRules (), hammerRules (), sawRules ()),
129150 },
130151 {
131152 name : "no diff skip" ,
132153 startingClusterRoles : []* rbacv1.ClusterRole {
133154 role ("hammer" , map [string ]string {"foo" : "bar" }, hammerRules ()),
134155 combinedRole ([]map [string ]string {{"foo" : "bar" }}, hammerRules ()),
135156 },
136- clusterRoleToSync : "combined" ,
137- expectedClusterRole : nil ,
157+ clusterRoleToSync : "combined" ,
158+ expectedClusterRoleApply : nil ,
138159 }}
139160
140- for _ , test := range tests {
141- t .Run (test .name , func (t * testing.T ) {
142- indexer := cache .NewIndexer (controller .KeyFunc , cache.Indexers {})
143- objs := []runtime.Object {}
144- for _ , obj := range test .startingClusterRoles {
145- objs = append (objs , obj )
146- indexer .Add (obj )
147- }
148- fakeClient := fakeclient .NewSimpleClientset (objs ... )
149- c := ClusterRoleAggregationController {
150- clusterRoleClient : fakeClient .RbacV1 (),
151- clusterRoleLister : rbaclisters .NewClusterRoleLister (indexer ),
152- }
153- err := c .syncClusterRole (test .clusterRoleToSync )
154- if err != nil {
155- t .Fatal (err )
156- }
157-
158- if test .expectedClusterRole == nil {
159- if len (fakeClient .Actions ()) != 0 {
161+ for _ , serverSideApplyEnabled := range []bool {true , false } {
162+ for _ , test := range tests {
163+ t .Run (test .name , func (t * testing.T ) {
164+ indexer := cache .NewIndexer (controller .KeyFunc , cache.Indexers {})
165+ objs := []runtime.Object {}
166+ for _ , obj := range test .startingClusterRoles {
167+ objs = append (objs , obj )
168+ indexer .Add (obj )
169+ }
170+ fakeClient := fakeclient .NewSimpleClientset (objs ... )
171+
172+ // The default reactor doesn't support apply, so we need our own (trivial) reactor
173+ fakeClient .PrependReactor ("patch" , "clusterroles" , func (action clienttesting.Action ) (handled bool , ret runtime.Object , err error ) {
174+ if serverSideApplyEnabled == false {
175+ // UnsupportedMediaType
176+ return true , nil , errors .NewGenericServerResponse (415 , "get" , action .GetResource ().GroupResource (), "test" , "Apply not supported" , 0 , true )
177+ }
178+ return true , nil , nil // clusterroleaggregator drops returned objects so no point in constructing them
179+ })
180+ c := ClusterRoleAggregationController {
181+ clusterRoleClient : fakeClient .RbacV1 (),
182+ clusterRoleLister : rbaclisters .NewClusterRoleLister (indexer ),
183+ }
184+ err := c .syncClusterRole (test .clusterRoleToSync )
185+ if err != nil {
186+ t .Fatal (err )
187+ }
188+
189+ if test .expectedClusterRoleApply == nil {
190+ if len (fakeClient .Actions ()) != 0 {
191+ t .Fatalf ("unexpected actions %#v" , fakeClient .Actions ())
192+ }
193+ return
194+ }
195+
196+ expectedActions := 1
197+ if ! serverSideApplyEnabled {
198+ expectedActions = 2
199+ }
200+ if len (fakeClient .Actions ()) != expectedActions {
160201 t .Fatalf ("unexpected actions %#v" , fakeClient .Actions ())
161202 }
162- return
163- }
164- if len (fakeClient .Actions ()) != 1 {
165- t .Fatalf ("unexpected actions %#v" , fakeClient .Actions ())
166- }
167-
168- action := fakeClient .Actions ()[0 ]
169- if ! action .Matches ("update" , "clusterroles" ) {
170- t .Fatalf ("unexpected action %#v" , action )
171- }
172- updateAction , ok := action .(clienttesting.UpdateAction )
173- if ! ok {
174- t .Fatalf ("unexpected action %#v" , action )
175- }
176- if ! equality .Semantic .DeepEqual (updateAction .GetObject ().(* rbacv1.ClusterRole ), test .expectedClusterRole ) {
177- t .Fatalf ("%v" , diff .ObjectDiff (test .expectedClusterRole , updateAction .GetObject ().(* rbacv1.ClusterRole )))
178-
179- }
180- })
203+
204+ action := fakeClient .Actions ()[0 ]
205+ if ! action .Matches ("patch" , "clusterroles" ) {
206+ t .Fatalf ("unexpected action %#v" , action )
207+ }
208+ applyAction , ok := action .(clienttesting.PatchAction )
209+ if ! ok {
210+ t .Fatalf ("unexpected action %#v" , action )
211+ }
212+ ac := & rbacv1ac.ClusterRoleApplyConfiguration {}
213+ if err := yaml .Unmarshal (applyAction .GetPatch (), ac ); err != nil {
214+ t .Fatalf ("error unmarshalling apply request: %v" , err )
215+ }
216+ if ! equality .Semantic .DeepEqual (ac , test .expectedClusterRoleApply ) {
217+ t .Fatalf ("%v" , diff .ObjectDiff (test .expectedClusterRoleApply , ac ))
218+ }
219+ if expectedActions == 2 {
220+ action := fakeClient .Actions ()[1 ]
221+ if ! action .Matches ("update" , "clusterroles" ) {
222+ t .Fatalf ("unexpected action %#v" , action )
223+ }
224+ updateAction , ok := action .(clienttesting.UpdateAction )
225+ if ! ok {
226+ t .Fatalf ("unexpected action %#v" , action )
227+ }
228+ if ! equality .Semantic .DeepEqual (updateAction .GetObject ().(* rbacv1.ClusterRole ), test .expectedClusterRole ) {
229+ t .Fatalf ("%v" , diff .ObjectDiff (test .expectedClusterRole , updateAction .GetObject ().(* rbacv1.ClusterRole )))
230+ }
231+ }
232+ })
233+ }
181234 }
182235}
0 commit comments