@@ -26,13 +26,17 @@ import (
2626 "k8s.io/utils/clock"
2727
2828 "github.com/ghodss/yaml"
29+ "github.com/google/go-cmp/cmp"
2930 "github.com/openshift/api/annotations"
3031 kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1"
3132 operatorv1 "github.com/openshift/api/operator/v1"
33+ "github.com/openshift/cluster-kube-apiserver-operator/bindata"
3234 "github.com/openshift/cluster-kube-apiserver-operator/pkg/operator/operatorclient"
3335 "github.com/openshift/library-go/pkg/operator/events"
3436 "github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
37+ "github.com/openshift/library-go/pkg/operator/resource/resourceread"
3538 "github.com/stretchr/testify/require"
39+ clientgotesting "k8s.io/client-go/testing"
3640)
3741
3842var codec = scheme .Codecs .LegacyCodec (scheme .Scheme .PrioritizedVersionsAllGroups ()... )
@@ -1217,3 +1221,166 @@ func generateTemporaryCertificate() (certPEM []byte, err error) {
12171221
12181222 return certPEM , nil
12191223}
1224+
1225+ // TestEnsureKubeAPIServerExtensionAuthenticationCA tests the behavior of ensureKubeAPIServerExtensionAuthenticationCA
1226+ func TestEnsureKubeAPIServerExtensionAuthenticationCA (t * testing.T ) {
1227+ ctx := context .Background ()
1228+ recorder := events .NewInMemoryRecorder ("test" , clock.RealClock {})
1229+
1230+ t .Run ("configmap not found (Get error)" , func (t * testing.T ) {
1231+ // Create a fake client with no configmap in kube-system
1232+ client := fake .NewSimpleClientset ()
1233+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1234+ if err != nil {
1235+ t .Fatalf ("expected nil error when configmap is missing, got: %v" , err )
1236+ }
1237+ })
1238+
1239+ t .Run ("configmap exists but missing annotations, update succeeds" , func (t * testing.T ) {
1240+ // Create a configmap without annotations
1241+ cm := & corev1.ConfigMap {
1242+ ObjectMeta : metav1.ObjectMeta {
1243+ Name : "extension-apiserver-authentication" ,
1244+ Namespace : "kube-system" ,
1245+ },
1246+ }
1247+ client := fake .NewSimpleClientset (cm )
1248+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1249+ if err != nil {
1250+ t .Fatalf ("expected nil error after update, got: %v" , err )
1251+ }
1252+ updatedCM , err := client .CoreV1 ().ConfigMaps ("kube-system" ).Get (ctx , "extension-apiserver-authentication" , metav1.GetOptions {})
1253+ if err != nil {
1254+ t .Fatalf ("failed to get updated configmap: %v" , err )
1255+ }
1256+ if updatedCM .Annotations == nil || updatedCM .Annotations [annotations .OpenShiftComponent ] != "kube-apiserver" {
1257+ t .Fatalf ("expected annotation not set, got: %v" , updatedCM .Annotations )
1258+ }
1259+ })
1260+
1261+ t .Run ("configmap exists with correct annotations, no update needed" , func (t * testing.T ) {
1262+ required := resourceread .ReadConfigMapV1OrDie (bindata .MustAsset ("assets/kube-apiserver/extension-apiserver-authentication-cm.yaml" ))
1263+
1264+ // Create a configmap with the expected annotation already present
1265+ cm := & corev1.ConfigMap {
1266+ ObjectMeta : metav1.ObjectMeta {
1267+ Name : "extension-apiserver-authentication" ,
1268+ Namespace : "kube-system" ,
1269+ Annotations : required .Annotations ,
1270+ },
1271+ }
1272+ client := fake .NewSimpleClientset (cm )
1273+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1274+ if err != nil {
1275+ t .Fatalf ("expected nil error when annotations are already correct, got: %v" , err )
1276+ }
1277+
1278+ // Check that client only did one action)
1279+ if len (client .Actions ()) != 1 {
1280+ t .Fatalf ("expected one action, got: %v" , client .Actions ())
1281+ }
1282+ action := client .Actions ()[0 ]
1283+ if action .GetVerb () != "get" {
1284+ t .Fatalf ("expected get action, got: %v" , action )
1285+ }
1286+ getAction := action .(clientgotesting.GetAction )
1287+ if getAction .GetName () != "extension-apiserver-authentication" {
1288+ t .Fatalf ("expected get action for configmap 'extension-apiserver-authentication', got: %v" , getAction )
1289+ }
1290+ if getAction .GetNamespace () != "kube-system" {
1291+ t .Fatalf ("expected get action for namespace 'kube-system', got: %v" , getAction )
1292+ }
1293+ })
1294+
1295+ t .Run ("update failure propagates error" , func (t * testing.T ) {
1296+ // Create a configmap without annotations
1297+ cm := & corev1.ConfigMap {
1298+ ObjectMeta : metav1.ObjectMeta {
1299+ Name : "extension-apiserver-authentication" ,
1300+ Namespace : "kube-system" ,
1301+ },
1302+ }
1303+ client := fake .NewSimpleClientset (cm )
1304+
1305+ // Inject reactor to simulate update failure
1306+ client .Fake .PrependReactor ("update" , "configmaps" , func (action clientgotesting.Action ) (bool , runtime.Object , error ) {
1307+ return true , nil , fmt .Errorf ("simulated update failure" )
1308+ })
1309+
1310+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1311+ if err == nil || ! strings .Contains (err .Error (), "simulated update failure" ) {
1312+ t .Fatalf ("expected update failure error, got: %v" , err )
1313+ }
1314+ })
1315+
1316+ t .Run ("unrelated annotations are not removed" , func (t * testing.T ) {
1317+ unrelatedAnnotations := map [string ]string {
1318+ "unrelated.annotation/key1" : "value1" ,
1319+ "unrelated.annotation/key2" : "value2" ,
1320+ }
1321+
1322+ // Create a configmap with unrelated annotations
1323+ cm := & corev1.ConfigMap {
1324+ ObjectMeta : metav1.ObjectMeta {
1325+ Name : "extension-apiserver-authentication" ,
1326+ Namespace : "kube-system" ,
1327+ Annotations : unrelatedAnnotations ,
1328+ },
1329+ }
1330+ client := fake .NewSimpleClientset (cm )
1331+
1332+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1333+ if err != nil {
1334+ t .Fatalf ("expected nil error, got: %v" , err )
1335+ }
1336+
1337+ updatedCM , err := client .CoreV1 ().ConfigMaps ("kube-system" ).Get (ctx , "extension-apiserver-authentication" , metav1.GetOptions {})
1338+ if err != nil {
1339+ t .Fatalf ("failed to get updated configmap: %v" , err )
1340+ }
1341+
1342+ required := resourceread .ReadConfigMapV1OrDie (bindata .MustAsset ("assets/kube-apiserver/extension-apiserver-authentication-cm.yaml" ))
1343+
1344+ expectedAnnotations := map [string ]string {}
1345+ for k , v := range required .Annotations {
1346+ expectedAnnotations [k ] = v
1347+ }
1348+ for k , v := range unrelatedAnnotations {
1349+ expectedAnnotations [k ] = v
1350+ }
1351+
1352+ diff := cmp .Diff (expectedAnnotations , updatedCM .Annotations )
1353+ if diff != "" {
1354+ t .Fatalf ("expected annotations to match, but got diff:\n %s" , diff )
1355+ }
1356+ })
1357+
1358+ t .Run ("configmap exists with incorrect OpenShiftComponent annotation, update succeeds" , func (t * testing.T ) {
1359+ // Create a configmap with an incorrect OpenShiftComponent annotation
1360+ cm := & corev1.ConfigMap {
1361+ ObjectMeta : metav1.ObjectMeta {
1362+ Name : "extension-apiserver-authentication" ,
1363+ Namespace : "kube-system" ,
1364+ Annotations : map [string ]string {
1365+ annotations .OpenShiftComponent : "incorrect-value" ,
1366+ },
1367+ },
1368+ }
1369+ client := fake .NewSimpleClientset (cm )
1370+
1371+ err := ensureKubeAPIServerExtensionAuthenticationCA (ctx , client .CoreV1 (), recorder )
1372+ if err != nil {
1373+ t .Fatalf ("expected nil error, got: %v" , err )
1374+ }
1375+
1376+ updatedCM , err := client .CoreV1 ().ConfigMaps ("kube-system" ).Get (ctx , "extension-apiserver-authentication" , metav1.GetOptions {})
1377+ if err != nil {
1378+ t .Fatalf ("failed to get updated configmap: %v" , err )
1379+ }
1380+
1381+ // Verify the OpenShiftComponent annotation is updated to the correct value
1382+ if updatedCM .Annotations == nil || updatedCM .Annotations [annotations .OpenShiftComponent ] != "kube-apiserver" {
1383+ t .Errorf ("expected annotation %s=kube-apiserver, got: %v" , annotations .OpenShiftComponent , updatedCM .Annotations )
1384+ }
1385+ })
1386+ }
0 commit comments