diff --git a/api/v1/cluster_types.go b/api/v1/cluster_types.go index 37d733d1a0..d3d2f33c2a 100644 --- a/api/v1/cluster_types.go +++ b/api/v1/cluster_types.go @@ -1013,6 +1013,11 @@ type Import struct { // database right after is imported - to be used with extreme care // (by default empty). Only available in microservice type. PostImportApplicationSQL []string `json:"postImportApplicationSQL,omitempty"` + + // When set to true, only the `pre-data` and `post-data` sections of + // `pg_restore` are invoked, avoiding data import. Default: `false`. + // +kubebuilder:default:=false + SchemaOnly bool `json:"schemaOnly,omitempty"` } // ImportSource describes the source for the logical snapshot diff --git a/config/crd/bases/postgresql.cnpg.io_clusters.yaml b/config/crd/bases/postgresql.cnpg.io_clusters.yaml index 8b9b235e59..5cbe83cdb2 100644 --- a/config/crd/bases/postgresql.cnpg.io_clusters.yaml +++ b/config/crd/bases/postgresql.cnpg.io_clusters.yaml @@ -1272,6 +1272,12 @@ spec: items: type: string type: array + schemaOnly: + default: false + description: 'When set to true, only the `pre-data` and + `post-data` sections of `pg_restore` are invoked, avoiding + data import. Default: `false`.' + type: boolean source: description: The source of the import properties: diff --git a/docs/src/api_reference.md b/docs/src/api_reference.md index 8809382442..6266588e7d 100644 --- a/docs/src/api_reference.md +++ b/docs/src/api_reference.md @@ -530,6 +530,7 @@ Name | Description `databases ` | The databases to import - *mandatory* | []string `roles ` | The roles to import | []string `postImportApplicationSQL` | List of SQL queries to be executed as a superuser in the application database right after is imported - to be used with extreme care (by default empty). Only available in microservice type. | []string +`schemaOnly ` | When set to true, only the `pre-data` and `post-data` sections of `pg_restore` are invoked, avoiding data import. Default: `false`. | bool diff --git a/docs/src/samples/cluster-import-schema-only-basicauth.yaml b/docs/src/samples/cluster-import-schema-only-basicauth.yaml new file mode 100644 index 0000000000..b3bae44f8f --- /dev/null +++ b/docs/src/samples/cluster-import-schema-only-basicauth.yaml @@ -0,0 +1,27 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: cluster-pgdump +spec: + instances: 3 + + bootstrap: + initdb: + import: + type: microservice + schemaOnly: true + databases: + - app + source: + externalCluster: cluster-example + storage: + size: 1Gi + externalClusters: + - name: cluster-example + connectionParameters: + host: cluster-example-rw.default.svc + user: postgres + dbname: postgres + password: + name: cluster-example-superuser + key: password diff --git a/pkg/management/postgres/logicalimport/database.go b/pkg/management/postgres/logicalimport/database.go index 8c9ca9ca5d..9eda158114 100644 --- a/pkg/management/postgres/logicalimport/database.go +++ b/pkg/management/postgres/logicalimport/database.go @@ -90,6 +90,12 @@ func (ds *databaseSnapshotter) exportDatabases( databases []string, ) error { contextLogger := log.FromContext(ctx) + sectionsToExport := []string{} + + for _, section := range ds.getSectionsToExecute() { + sectionsToExport = append(sectionsToExport, fmt.Sprintf("--section=%s", section)) + } + for _, database := range databases { contextLogger.Info("exporting database", "databaseName", database) dsn := target.GetDsn(database) @@ -99,6 +105,7 @@ func (ds *databaseSnapshotter) exportDatabases( "-d", dsn, "-v", } + options = append(options, sectionsToExport...) contextLogger.Info("Running pg_dump", "cmd", pgDump, "options", options) @@ -120,7 +127,7 @@ func (ds *databaseSnapshotter) importDatabases( contextLogger := log.FromContext(ctx) for _, database := range databases { - for _, section := range []string{"pre-data", "data", "post-data"} { + for _, section := range ds.getSectionsToExecute() { targetDatabase := target.GetDsn(database) contextLogger.Info( "executing database importing section", @@ -190,7 +197,7 @@ func (ds *databaseSnapshotter) importDatabaseContent( return err } - for _, section := range []string{"pre-data", "data", "post-data"} { + for _, section := range ds.getSectionsToExecute() { contextLogger.Info( "executing database importing section", "databaseName", database, @@ -340,3 +347,20 @@ func (ds *databaseSnapshotter) dropExtensionsFromDatabase( return rows.Err() } + +// getSectionsToExecute determines which stages of `pg_restore` and `pg_dump` to execute, +// based on the configuration of the cluster. It returns a slice of strings representing +// the sections to execute. These sections are labeled as "pre-data", "data", and "post-data". +func (ds *databaseSnapshotter) getSectionsToExecute() []string { + const ( + preData = "pre-data" + data = "data" + postData = "post-data" + ) + + if ds.cluster.Spec.Bootstrap.InitDB.Import.SchemaOnly { + return []string{preData, postData} + } + + return []string{preData, data, postData} +}