Skip to content

Commit 56c9f76

Browse files
pooknullhors
andauthored
K8SPG-698: create serviceaccount before statefulset (#1125)
* K8SPG-698: create serviceaccount before statefulset https://perconadev.atlassian.net/browse/K8SPG-698 * small fixes * remove update * fix lint --------- Co-authored-by: Viacheslav Sarzhan <[email protected]>
1 parent f0f13b4 commit 56c9f76

File tree

2 files changed

+117
-8
lines changed

2 files changed

+117
-8
lines changed

Diff for: internal/controller/postgrescluster/pgbackrest.go

+9-8
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,15 @@ func (r *Reconciler) reconcilePGBackRest(ctx context.Context,
14841484
return result, nil
14851485
}
14861486

1487+
// reconcile the RBAC required to run pgBackRest Jobs (e.g. for backups)
1488+
// K8SPG-698
1489+
sa, err := r.reconcilePGBackRestRBAC(ctx, postgresCluster)
1490+
if err != nil {
1491+
log.Error(err, "unable to create replica creation backup")
1492+
result.Requeue = true
1493+
return result, nil
1494+
}
1495+
14871496
var repoHost *appsv1.StatefulSet
14881497
var repoHostName string
14891498
// reconcile the pgbackrest repository host
@@ -1532,14 +1541,6 @@ func (r *Reconciler) reconcilePGBackRest(ctx context.Context,
15321541
result.Requeue = true
15331542
}
15341543

1535-
// reconcile the RBAC required to run pgBackRest Jobs (e.g. for backups)
1536-
sa, err := r.reconcilePGBackRestRBAC(ctx, postgresCluster)
1537-
if err != nil {
1538-
log.Error(err, "unable to create replica creation backup")
1539-
result.Requeue = true
1540-
return result, nil
1541-
}
1542-
15431544
// reconcile the pgBackRest stanza for all configuration pgBackRest repos
15441545
configHashMismatch, err := r.reconcileStanzaCreate(ctx, postgresCluster, instances, configHash)
15451546
// If a stanza create error then requeue but don't return the error. This prevents

Diff for: percona/controller/pgcluster/controller_test.go

+108
Original file line numberDiff line numberDiff line change
@@ -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+
16261734
var _ = Describe("CR Validations", Ordered, func() {
16271735
ctx := context.Background()
16281736
const crName = "cr-validation"

0 commit comments

Comments
 (0)