@@ -1623,6 +1623,114 @@ var _ = Describe("Validate TLS", Ordered, func() {
16231623 })
16241624})
16251625
1626+ type saTestClient struct {
1627+ client.Client
1628+
1629+ crName string
1630+ ns string
1631+ }
1632+
1633+ func (sc * saTestClient ) checkObject (ctx context.Context , obj client.Object ) error {
1634+ sts , ok := obj .(* appsv1.StatefulSet )
1635+ if ! ok {
1636+ return nil
1637+ }
1638+ serviceAccountName := sts .Spec .Template .Spec .ServiceAccountName
1639+ if serviceAccountName == "" {
1640+ return errors .New ("it's not expected to have empty service account name" )
1641+ }
1642+
1643+ if err := sc .Get (ctx , types.NamespacedName {
1644+ Name : serviceAccountName ,
1645+ Namespace : sts .Namespace ,
1646+ }, new (corev1.ServiceAccount )); err != nil {
1647+ if k8serrors .IsNotFound (err ) {
1648+ return errors .Wrap (err , "test error: service account should be created before the statefulset" )
1649+ }
1650+ return err
1651+ }
1652+
1653+ return nil
1654+ }
1655+
1656+ func (sc * saTestClient ) Patch (ctx context.Context , obj client.Object , patch client.Patch , opts ... client.PatchOption ) error {
1657+ if err := sc .checkObject (ctx , obj ); err != nil {
1658+ panic (err ) // should panic because reconciler can ignore the error
1659+ }
1660+ return sc .Client .Patch (ctx , obj , patch , opts ... )
1661+ }
1662+
1663+ func (sc * saTestClient ) Create (ctx context.Context , obj client.Object , opts ... client.CreateOption ) error {
1664+ if err := sc .checkObject (ctx , obj ); err != nil {
1665+ panic (err ) // should panic because reconciler can ignore the error
1666+ }
1667+ return sc .Client .Create (ctx , obj , opts ... )
1668+ }
1669+
1670+ // This test ensures that the ServiceAccount associated with a StatefulSet is created
1671+ // before the StatefulSet itself. (K8SPG-698)
1672+ // The saTestClient verifies the existence of the ServiceAccount during create, patch,
1673+ // or update operations on the StatefulSet.
1674+ var _ = Describe ("ServiceAccount early creation" , Ordered , func () {
1675+ ctx := context .Background ()
1676+
1677+ const crName = "sa-timestamp"
1678+ const ns = crName
1679+
1680+ namespace := & corev1.Namespace {
1681+ ObjectMeta : metav1.ObjectMeta {
1682+ Name : crName ,
1683+ Namespace : ns ,
1684+ },
1685+ }
1686+ crNamespacedName := types.NamespacedName {Name : crName , Namespace : ns }
1687+
1688+ cr , err := readDefaultCR (crName , ns )
1689+ It ("should read default cr.yaml" , func () {
1690+ Expect (err ).NotTo (HaveOccurred ())
1691+ })
1692+
1693+ cr .Default ()
1694+ reconciler := reconciler (cr )
1695+ crunchyReconciler := crunchyReconciler ()
1696+
1697+ var cl client.Client
1698+
1699+ BeforeAll (func () {
1700+ cl = & saTestClient {
1701+ Client : k8sClient ,
1702+
1703+ crName : crName ,
1704+ ns : ns ,
1705+ }
1706+ reconciler .Client = cl
1707+ crunchyReconciler .Client = cl
1708+
1709+ By ("Creating the Namespace to perform the tests" )
1710+ err := cl .Create (ctx , namespace )
1711+ Expect (err ).To (Not (HaveOccurred ()))
1712+ })
1713+
1714+ AfterAll (func () {
1715+ By ("Deleting the Namespace to perform the tests" )
1716+ _ = cl .Delete (ctx , namespace )
1717+ })
1718+
1719+ It ("should create PerconaPGCluster" , func () {
1720+ status := cr .Status
1721+ Expect (cl .Create (ctx , cr )).Should (Succeed ())
1722+ cr .Status = status
1723+ Expect (cl .Status ().Update (ctx , cr )).Should (Succeed ())
1724+ })
1725+
1726+ It ("Should reconcile" , func () {
1727+ _ , err := reconciler .Reconcile (ctx , ctrl.Request {NamespacedName : crNamespacedName })
1728+ Expect (err ).NotTo (HaveOccurred ())
1729+ _ , err = crunchyReconciler .Reconcile (ctx , ctrl.Request {NamespacedName : crNamespacedName })
1730+ Expect (err ).NotTo (HaveOccurred ())
1731+ })
1732+ })
1733+
16261734var _ = Describe ("CR Validations" , Ordered , func () {
16271735 ctx := context .Background ()
16281736 const crName = "cr-validation"
0 commit comments