From 808884e01f5257de6a5305e6b22c219e6ad96d11 Mon Sep 17 00:00:00 2001
From: Gabriele Quaresima
allTables
[Required]All tables should be publicated
@@ -4132,19 +4132,6 @@ desired state that was synchronizedPublicationTargetAllTables means all tables should be publicated
- - - - ## PublicationTargetObject {#postgresql-cnpg-io-v1-PublicationTargetObject} diff --git a/docs/src/declarative_publication_subscription_management.md b/docs/src/declarative_publication_subscription_management.md new file mode 100644 index 0000000000..adeb00eb41 --- /dev/null +++ b/docs/src/declarative_publication_subscription_management.md @@ -0,0 +1,135 @@ +# Declarative Publication/Subscription Management + +Declarative publication/subscription management enables users to set up +logical replication via new Custom Resource Definitions (CRD) +- `Database` , +- `Publication`, +- `Subscription`, + +Database CRD is widely discussed in +["Declarative database management"](declarative_database_management.md) section. + +Logical replication is set up between one source cluster with publication +and one destination cluster that is subscribed to that publication. + +### Example: Simple Publication Declaration + +A `Publication` object is managed by the instance manager of the source cluster's +primary instance. +Below is an example of a basic `Publication` configuration: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Publication +metadata: + name: pub-one +spec: + name: pub + dbname: cat + cluster: + name: source-cluster + target: + allTables: true +``` + +The `dbname` field specifies the database the publication is applied to. +Once the reconciliation cycle is completed successfully, the `Publication` +status will show a `ready` field set to `true` and an empty `error` field. + +### Publication Deletion and Reclaim Policies + +A finalizer named `cnpg.io/deletePublication` is automatically added +to each `Publication` object to control its deletion process. + +By default, the `publicationReclaimPolicy` is set to `retain`, which means +that if the `Publication` object is deleted, the actual PostgreSQL publication +is retained for manual management by an administrator. + +Alternatively, if the `publicationReclaimPolicy` is set to `delete`, +the PostgreSQL publication will be automatically deleted when the `Publication` +object is removed. + +### Example: Publication with Delete Reclaim Policy + +The following example illustrates a `Publication` object with a `delete` +reclaim policy: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Publication +metadata: + name: pub-one +spec: + name: pub + dbname: cat + publicationReclaimPolicy: delete + cluster: + name: source-cluster + target: + allTables: true +``` + +In this case, when the `Publication` object is deleted, the corresponding PostgreSQL publication will also be removed automatically. + + +### Example: Simple Subscription Declaration + +A `Subscription` object is managed by the instance manager of the destination cluster's +primary instance. +Below is an example of a basic `Subscription` configuration: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Subscription +metadata: + name: sub-one +spec: + name: sub + dbname: cat + publicationName: pub + cluster: + name: destination-cluster + externalClusterName: source-cluster +``` + +The `dbname` field specifies the database the publication is applied to. +The `publicationName` field specifies the name of the publication the subscription refers to. +The `externalClusterName` field specifies the external cluster the publication belongs to. + +Once the reconciliation cycle is completed successfully, the `Subscription` +status will show a `ready` field set to `true` and an empty `error` field. + +### Subscription Deletion and Reclaim Policies + +A finalizer named `cnpg.io/deleteSubscription` is automatically added +to each `Subscription` object to control its deletion process. + +By default, the `subscriptionReclaimPolicy` is set to `retain`, which means +that if the `Subscription` object is deleted, the actual PostgreSQL publication +is retained for manual management by an administrator. + +Alternatively, if the `subscriptionReclaimPolicy` is set to `delete`, +the PostgreSQL publication will be automatically deleted when the `Publication` +object is removed. + +### Example: Subscription with Delete Reclaim Policy + +The following example illustrates a `Subscription` object with a `delete` +reclaim policy: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Subscription +metadata: + name: sub-one +spec: + name: sub + dbname: cat + publicationName: pub + subscriptionReclaimPolicy: delete + cluster: + name: destination-cluster + externalClusterName: source-cluster +``` + +In this case, when the `Subscription` object is deleted, the corresponding PostgreSQL publication will also be removed automatically. diff --git a/internal/management/controller/publication_controller_sql.go b/internal/management/controller/publication_controller_sql.go index 4006c81463..8afe8c5dd5 100644 --- a/internal/management/controller/publication_controller_sql.go +++ b/internal/management/controller/publication_controller_sql.go @@ -176,7 +176,7 @@ func (r *PublicationReconciler) dropPublication(ctx context.Context, obj *apiv1. } func toPublicationTargetSQL(obj *apiv1.PublicationTarget) string { - if obj.AllTables != nil { + if obj.AllTables { return "FOR ALL TABLES" } diff --git a/tests/e2e/asserts_test.go b/tests/e2e/asserts_test.go index badcfe420c..55caaeaf0e 100644 --- a/tests/e2e/asserts_test.go +++ b/tests/e2e/asserts_test.go @@ -476,6 +476,30 @@ func AssertCreateTestDataWithDatabaseName( }) } +// AssertCreateTestDataWithDatabaseName create test data in a given database. +func AssertCreateTableWithDatabaseName( + env *testsUtils.TestingEnvironment, + namespace, + clusterName, + databaseName, + tableName string, +) { + By(fmt.Sprintf("creating table in cluster %v", clusterName), func() { + forward, conn, err := testsUtils.ForwardPSQLConnection( + env, + namespace, + clusterName, + databaseName, + apiv1.ApplicationUserSecretSuffix, + ) + Expect(err).ToNot(HaveOccurred()) + query := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %v ();", tableName) + _, err = conn.Exec(query) + Expect(err).ToNot(HaveOccurred()) + forward.Close() + }) +} + type TableLocator struct { Namespace string ClusterName string diff --git a/tests/e2e/declarative_pub_sub_test.go b/tests/e2e/declarative_pub_sub_test.go index 84ed803031..fb7b9dbd08 100644 --- a/tests/e2e/declarative_pub_sub_test.go +++ b/tests/e2e/declarative_pub_sub_test.go @@ -169,6 +169,10 @@ var _ = Describe("Declarative publication and subscription test", Label(tests.La AssertDatabaseExists(namespace, primaryPodInfo.Name, dbname, true) }) + By("creating empty table inside destination database", func() { + AssertCreateTableWithDatabaseName(env, namespace, destinationClusterName, dbname, tableName) + }) + By("applying Publication CRD manifest", func() { CreateResourceFromFile(namespace, pubManifest) pubObjectName, err = env.GetResourceNameFromYAML(pubManifest) @@ -219,7 +223,7 @@ var _ = Describe("Declarative publication and subscription test", Label(tests.La assertSubscriptionExists(namespace, primaryPodInfo.Name, sub) }) - By("creating a new data in the source cluster database", func() { + By("creating new data in the source cluster database", func() { AssertCreateTestDataWithDatabaseName(env, namespace, sourceClusterName, dbname, tableName) }) diff --git a/tests/e2e/fixtures/declarative_pub_sub/pub.yaml.template b/tests/e2e/fixtures/declarative_pub_sub/pub.yaml.template index 1fa6bada73..bd09d64014 100644 --- a/tests/e2e/fixtures/declarative_pub_sub/pub.yaml.template +++ b/tests/e2e/fixtures/declarative_pub_sub/pub.yaml.template @@ -8,4 +8,4 @@ spec: cluster: name: source-cluster target: - allTables: {} + allTables: true