k8s.io/apiserver@v0.31.1/pkg/server/options/admission_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package options 18 19 import ( 20 "fmt" 21 "io" 22 "testing" 23 24 "k8s.io/apimachinery/pkg/util/sets" 25 "k8s.io/apiserver/pkg/admission" 26 ) 27 28 func TestEnabledPluginNames(t *testing.T) { 29 scenarios := []struct { 30 expectedPluginNames []string 31 setDefaultOffPlugins sets.Set[string] 32 setRecommendedPluginOrder []string 33 setEnablePlugins []string 34 setDisablePlugins []string 35 setAdmissionControl []string 36 }{ 37 // scenario 0: check if a call to enabledPluginNames sets expected values. 38 { 39 expectedPluginNames: []string{"NamespaceLifecycle", "MutatingAdmissionWebhook", "ValidatingAdmissionPolicy", "ValidatingAdmissionWebhook"}, 40 }, 41 42 // scenario 1: use default off plugins if no specified 43 { 44 expectedPluginNames: []string{"pluginB"}, 45 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 46 setDefaultOffPlugins: sets.New("pluginA", "pluginC", "pluginD"), 47 }, 48 49 // scenario 2: use default off plugins and with RecommendedPluginOrder 50 { 51 expectedPluginNames: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 52 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 53 setDefaultOffPlugins: sets.Set[string]{}, 54 }, 55 56 // scenario 3: use default off plugins and specified by enable-admission-plugins with RecommendedPluginOrder 57 { 58 expectedPluginNames: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 59 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 60 setDefaultOffPlugins: sets.New("pluginC", "pluginD"), 61 setEnablePlugins: []string{"pluginD", "pluginC"}, 62 }, 63 64 // scenario 4: use default off plugins and specified by disable-admission-plugins with RecommendedPluginOrder 65 { 66 expectedPluginNames: []string{"pluginB"}, 67 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 68 setDefaultOffPlugins: sets.New("pluginC", "pluginD"), 69 setDisablePlugins: []string{"pluginA"}, 70 }, 71 72 // scenario 5: use default off plugins and specified by enable-admission-plugins and disable-admission-plugins with RecommendedPluginOrder 73 { 74 expectedPluginNames: []string{"pluginA", "pluginC"}, 75 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 76 setDefaultOffPlugins: sets.New("pluginC", "pluginD"), 77 setEnablePlugins: []string{"pluginC"}, 78 setDisablePlugins: []string{"pluginB"}, 79 }, 80 81 // scenario 6: use default off plugins and specified by admission-control with RecommendedPluginOrder 82 { 83 expectedPluginNames: []string{"pluginA", "pluginB", "pluginC"}, 84 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 85 setDefaultOffPlugins: sets.New("pluginD"), 86 setAdmissionControl: []string{"pluginA", "pluginB"}, 87 }, 88 89 // scenario 7: use default off plugins and specified by admission-control with RecommendedPluginOrder 90 { 91 expectedPluginNames: []string{"pluginA", "pluginB", "pluginC"}, 92 setRecommendedPluginOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 93 setDefaultOffPlugins: sets.New("pluginC", "pluginD"), 94 setAdmissionControl: []string{"pluginA", "pluginB", "pluginC"}, 95 }, 96 } 97 98 // act 99 for index, scenario := range scenarios { 100 t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) { 101 target := NewAdmissionOptions() 102 103 if scenario.setDefaultOffPlugins != nil { 104 target.DefaultOffPlugins = scenario.setDefaultOffPlugins 105 } 106 if scenario.setRecommendedPluginOrder != nil { 107 target.RecommendedPluginOrder = scenario.setRecommendedPluginOrder 108 } 109 if scenario.setEnablePlugins != nil { 110 target.EnablePlugins = scenario.setEnablePlugins 111 } 112 if scenario.setDisablePlugins != nil { 113 target.DisablePlugins = scenario.setDisablePlugins 114 } 115 if scenario.setAdmissionControl != nil { 116 target.EnablePlugins = scenario.setAdmissionControl 117 } 118 119 actualPluginNames := target.enabledPluginNames() 120 121 if len(actualPluginNames) != len(scenario.expectedPluginNames) { 122 t.Fatalf("incorrect number of items, got %d, expected = %d", len(actualPluginNames), len(scenario.expectedPluginNames)) 123 } 124 for i := range actualPluginNames { 125 if scenario.expectedPluginNames[i] != actualPluginNames[i] { 126 t.Errorf("missmatch at index = %d, got = %s, expected = %s", i, actualPluginNames[i], scenario.expectedPluginNames[i]) 127 } 128 } 129 }) 130 } 131 } 132 133 func TestValidate(t *testing.T) { 134 scenarios := []struct { 135 setEnablePlugins []string 136 setDisablePlugins []string 137 setRecommendedPluginsOrder []string 138 expectedResult bool 139 }{ 140 // scenario 0: not set any flag 141 { 142 expectedResult: true, 143 }, 144 145 // scenario 1: set both `--enable-admission-plugins` `--disable-admission-plugins` 146 { 147 setEnablePlugins: []string{"pluginA", "pluginB"}, 148 setDisablePlugins: []string{"pluginC"}, 149 expectedResult: true, 150 }, 151 152 // scenario 2: set invalid `--enable-admission-plugins` `--disable-admission-plugins` 153 { 154 setEnablePlugins: []string{"pluginA", "pluginB"}, 155 setDisablePlugins: []string{"pluginB"}, 156 expectedResult: false, 157 }, 158 159 // scenario 3: set only invalid `--enable-admission-plugins` 160 { 161 setEnablePlugins: []string{"pluginA", "pluginE"}, 162 expectedResult: false, 163 }, 164 165 // scenario 4: set only invalid `--disable-admission-plugins` 166 { 167 setDisablePlugins: []string{"pluginA", "pluginE"}, 168 expectedResult: false, 169 }, 170 171 // scenario 5: set valid `--enable-admission-plugins` 172 { 173 setEnablePlugins: []string{"pluginA", "pluginB"}, 174 expectedResult: true, 175 }, 176 177 // scenario 6: set valid `--disable-admission-plugins` 178 { 179 setDisablePlugins: []string{"pluginA"}, 180 expectedResult: true, 181 }, 182 183 // scenario 7: RecommendedPluginOrder has duplicated plugin 184 { 185 setRecommendedPluginsOrder: []string{"pluginA", "pluginB", "pluginB", "pluginC"}, 186 expectedResult: false, 187 }, 188 189 // scenario 8: RecommendedPluginOrder not equal to registered 190 { 191 setRecommendedPluginsOrder: []string{"pluginA", "pluginB", "pluginC"}, 192 expectedResult: false, 193 }, 194 195 // scenario 9: RecommendedPluginOrder equal to registered 196 { 197 setRecommendedPluginsOrder: []string{"pluginA", "pluginB", "pluginC", "pluginD"}, 198 expectedResult: true, 199 }, 200 201 // scenario 10: RecommendedPluginOrder not equal to registered 202 { 203 setRecommendedPluginsOrder: []string{"pluginA", "pluginB", "pluginC", "pluginE"}, 204 expectedResult: false, 205 }, 206 } 207 208 for index, scenario := range scenarios { 209 t.Run(fmt.Sprintf("scenario %d", index), func(t *testing.T) { 210 options := NewAdmissionOptions() 211 options.DefaultOffPlugins = sets.New("pluginC", "pluginD") 212 options.RecommendedPluginOrder = []string{"pluginA", "pluginB", "pluginC", "pluginD"} 213 options.Plugins = &admission.Plugins{} 214 for _, plugin := range options.RecommendedPluginOrder { 215 options.Plugins.Register(plugin, func(config io.Reader) (admission.Interface, error) { 216 return nil, nil 217 }) 218 } 219 220 if scenario.setEnablePlugins != nil { 221 options.EnablePlugins = scenario.setEnablePlugins 222 } 223 if scenario.setDisablePlugins != nil { 224 options.DisablePlugins = scenario.setDisablePlugins 225 } 226 if scenario.setRecommendedPluginsOrder != nil { 227 options.RecommendedPluginOrder = scenario.setRecommendedPluginsOrder 228 } 229 230 err := options.Validate() 231 if len(err) > 0 && scenario.expectedResult { 232 t.Errorf("Unexpected err: %v", err) 233 } 234 if len(err) == 0 && !scenario.expectedResult { 235 t.Errorf("Expect error, but got none") 236 } 237 }) 238 } 239 }