@@ -1316,4 +1316,159 @@ var _ = Describe("Heat controller", func() {
13161316 }, timeout , interval ).Should (Succeed ())
13171317 })
13181318 })
1319+
1320+ When ("ApplicationCredential consumer finalizer is managed" , func () {
1321+ var (
1322+ acSecretName string
1323+ servicePasswordSecret string
1324+ )
1325+
1326+ BeforeEach (func () {
1327+ servicePasswordSecret = "ac-test-osp-secret" //nolint:gosec // G101
1328+
1329+ DeferCleanup (
1330+ k8sClient .Delete , ctx , CreateHeatMessageBusSecret (namespace , HeatMessageBusSecretName ))
1331+ DeferCleanup (
1332+ k8sClient .Delete , ctx , CreateHeatSecret (namespace , servicePasswordSecret ))
1333+
1334+ acSecretName = "ac-heat-a1b2c-secret" //nolint:gosec // G101
1335+ secret := & corev1.Secret {
1336+ ObjectMeta : metav1.ObjectMeta {
1337+ Namespace : namespace ,
1338+ Name : acSecretName ,
1339+ },
1340+ Data : map [string ][]byte {
1341+ keystonev1 .ACIDSecretKey : []byte ("a1b2ctest-ac-id" ),
1342+ keystonev1 .ACSecretSecretKey : []byte ("test-ac-secret" ),
1343+ },
1344+ }
1345+ DeferCleanup (k8sClient .Delete , ctx , secret )
1346+ Expect (k8sClient .Create (ctx , secret )).To (Succeed ())
1347+
1348+ spec := GetDefaultHeatSpec ()
1349+ spec ["secret" ] = servicePasswordSecret
1350+ spec ["auth" ] = map [string ]interface {}{
1351+ "applicationCredentialSecret" : acSecretName ,
1352+ }
1353+ DeferCleanup (th .DeleteInstance , CreateHeat (heatName , spec ))
1354+ DeferCleanup (
1355+ mariadb .DeleteDBService ,
1356+ mariadb .CreateDBService (
1357+ namespace ,
1358+ GetHeat (heatName ).Spec .DatabaseInstance ,
1359+ corev1.ServiceSpec {
1360+ Ports : []corev1.ServicePort {{Port : 3306 }},
1361+ },
1362+ ),
1363+ )
1364+ DeferCleanup (keystone .DeleteKeystoneAPI , keystone .CreateKeystoneAPI (namespace ))
1365+ DeferCleanup (infra .DeleteMemcached , infra .CreateMemcached (namespace , "memcached" , memcachedSpec ))
1366+ infra .SimulateMemcachedReady (memcachedName )
1367+
1368+ heatDatabase := types.NamespacedName {
1369+ Namespace : namespace ,
1370+ Name : GetHeat (heatName ).Spec .DatabaseAccount ,
1371+ }
1372+ acc , accSecret := mariadb .CreateMariaDBAccountAndSecret (heatDatabase , mariadbv1.MariaDBAccountSpec {})
1373+ DeferCleanup (k8sClient .Delete , ctx , acc )
1374+ DeferCleanup (k8sClient .Delete , ctx , accSecret )
1375+
1376+ infra .SimulateTransportURLReady (heatTransportURLName )
1377+ mariadb .SimulateMariaDBAccountCompleted (heatDatabase )
1378+ mariadb .SimulateMariaDBDatabaseCompleted (types.NamespacedName {Namespace : namespace , Name : heat .DatabaseCRName })
1379+ th .SimulateJobSuccess (heatDbSyncName )
1380+ })
1381+
1382+ It ("should add the consumer finalizer to the AC secret" , func () {
1383+ Eventually (func (g Gomega ) {
1384+ secret := th .GetSecret (types.NamespacedName {
1385+ Namespace : namespace ,
1386+ Name : acSecretName ,
1387+ })
1388+ g .Expect (secret .Finalizers ).To (
1389+ ContainElement (heat .ACConsumerFinalizer ))
1390+ }, timeout , interval ).Should (Succeed ())
1391+ })
1392+
1393+ It ("should track the consumed AC secret in status" , func () {
1394+ Eventually (func (g Gomega ) {
1395+ h := GetHeat (heatName )
1396+ g .Expect (h .Status .ApplicationCredentialSecret ).To (Equal (acSecretName ))
1397+ }, timeout , interval ).Should (Succeed ())
1398+ })
1399+
1400+ It ("should move the finalizer from the old to the new secret on rotation" , func () {
1401+ Eventually (func (g Gomega ) {
1402+ secret := th .GetSecret (types.NamespacedName {
1403+ Namespace : namespace ,
1404+ Name : acSecretName ,
1405+ })
1406+ g .Expect (secret .Finalizers ).To (
1407+ ContainElement (heat .ACConsumerFinalizer ))
1408+ }, timeout , interval ).Should (Succeed ())
1409+
1410+ newACSecretName := "ac-heat-x9y8z-secret" //nolint:gosec // G101
1411+ newSecret := & corev1.Secret {
1412+ ObjectMeta : metav1.ObjectMeta {
1413+ Namespace : namespace ,
1414+ Name : newACSecretName ,
1415+ },
1416+ Data : map [string ][]byte {
1417+ keystonev1 .ACIDSecretKey : []byte ("x9y8zrotated-ac-id" ),
1418+ keystonev1 .ACSecretSecretKey : []byte ("rotated-ac-secret" ),
1419+ },
1420+ }
1421+ DeferCleanup (k8sClient .Delete , ctx , newSecret )
1422+ Expect (k8sClient .Create (ctx , newSecret )).To (Succeed ())
1423+
1424+ Eventually (func (g Gomega ) {
1425+ h := GetHeat (heatName )
1426+ h .Spec .Auth .ApplicationCredentialSecret = newACSecretName
1427+ g .Expect (k8sClient .Update (ctx , h )).Should (Succeed ())
1428+ }, timeout , interval ).Should (Succeed ())
1429+
1430+ Eventually (func (g Gomega ) {
1431+ secret := th .GetSecret (types.NamespacedName {
1432+ Namespace : namespace ,
1433+ Name : newACSecretName ,
1434+ })
1435+ g .Expect (secret .Finalizers ).To (
1436+ ContainElement (heat .ACConsumerFinalizer ))
1437+ }, timeout , interval ).Should (Succeed ())
1438+
1439+ Eventually (func (g Gomega ) {
1440+ secret := th .GetSecret (types.NamespacedName {
1441+ Namespace : namespace ,
1442+ Name : acSecretName ,
1443+ })
1444+ g .Expect (secret .Finalizers ).NotTo (
1445+ ContainElement (heat .ACConsumerFinalizer ))
1446+ }, timeout , interval ).Should (Succeed ())
1447+
1448+ Eventually (func (g Gomega ) {
1449+ h := GetHeat (heatName )
1450+ g .Expect (h .Status .ApplicationCredentialSecret ).To (Equal (newACSecretName ))
1451+ }, timeout , interval ).Should (Succeed ())
1452+ })
1453+
1454+ It ("should remove the consumer finalizer from AC secret on CR deletion" , func () {
1455+ Eventually (func (g Gomega ) {
1456+ secret := th .GetSecret (types.NamespacedName {
1457+ Namespace : namespace ,
1458+ Name : acSecretName ,
1459+ })
1460+ g .Expect (secret .Finalizers ).To (
1461+ ContainElement (heat .ACConsumerFinalizer ))
1462+ }, timeout , interval ).Should (Succeed ())
1463+
1464+ th .DeleteInstance (GetHeat (heatName ))
1465+
1466+ secret := th .GetSecret (types.NamespacedName {
1467+ Namespace : namespace ,
1468+ Name : acSecretName ,
1469+ })
1470+ Expect (secret .Finalizers ).NotTo (
1471+ ContainElement (heat .ACConsumerFinalizer ))
1472+ })
1473+ })
13191474})
0 commit comments