diff --git a/server/internal/resource/migrations/1_0_0.go b/server/internal/resource/migrations/1_0_0.go index ff07a906..19bad223 100644 --- a/server/internal/resource/migrations/1_0_0.go +++ b/server/internal/resource/migrations/1_0_0.go @@ -72,6 +72,7 @@ func (v *Version_1_0_0) Run(state *resource.State) error { } type v1_0_0_databaseParams struct { + databaseID string databaseName string databaseOwner string renameFrom string @@ -79,6 +80,7 @@ type v1_0_0_databaseParams struct { } func (v *Version_1_0_0) extractDatabaseParams(instances map[string]*resource.ResourceData) (*v1_0_0_databaseParams, error) { + var databaseID string var databaseName string var databaseOwner string var renameFrom string @@ -92,6 +94,7 @@ func (v *Version_1_0_0) extractDatabaseParams(instances map[string]*resource.Res if instance.Spec.DatabaseName == "" { continue } + databaseID = instance.Spec.DatabaseID databaseName = instance.Spec.DatabaseName for _, user := range instance.Spec.DatabaseUsers { if user.DBOwner { @@ -106,6 +109,7 @@ func (v *Version_1_0_0) extractDatabaseParams(instances map[string]*resource.Res } return &v1_0_0_databaseParams{ + databaseID: databaseID, databaseName: databaseName, databaseOwner: databaseOwner, renameFrom: renameFrom, @@ -117,6 +121,7 @@ func (v *Version_1_0_0) addDatabaseResources(state *resource.State, nodes map[st for _, node := range nodes { nodeName := node.Identifier.ID dbResource := &v1_0_0.PostgresDatabaseResource{ + DatabaseID: params.databaseID, NodeName: nodeName, DatabaseName: params.databaseName, Owner: params.databaseOwner, @@ -289,13 +294,35 @@ func (v *Version_1_0_0) migrateReplicationSlotResources(state *resource.State, p return nil } +func (v *Version_1_0_0) newReplicationSlotResource(sub v1_0_0.SubscriptionResource) (*resource.ResourceData, error) { + new := v1_0_0.ReplicationSlotResource{ + ProviderNode: sub.ProviderNode, + SubscriberNode: sub.SubscriberNode, + DatabaseName: sub.DatabaseName, + } + attrs, err := json.Marshal(new) + if err != nil { + return nil, fmt.Errorf("failed to marshal new replication slot resource: %w", err) + } + return &resource.ResourceData{ + Identifier: v1_0_0.ReplicationSlotResourceIdentifier(new.ProviderNode, new.SubscriberNode, new.DatabaseName), + Attributes: attrs, + Dependencies: []resource.Identifier{ + v1_0_0.PostgresDatabaseResourceIdentifier(new.ProviderNode, new.DatabaseName), + }, + Executor: resource.PrimaryExecutor(sub.ProviderNode), + ResourceVersion: "1", + }, nil +} + func (v *Version_1_0_0) migrateSubscriptionResources(state *resource.State, params *v1_0_0_databaseParams) error { - resources, ok := state.Resources[v0_0_0.ResourceTypeSubscription] + slots := state.Resources[v0_0_0.ResourceTypeReplicationSlot] + subs, ok := state.Resources[v0_0_0.ResourceTypeSubscription] if !ok { return nil } - adds := make([]*resource.ResourceData, 0, len(resources)) - for oldID, data := range resources { + adds := make([]*resource.ResourceData, 0, len(subs)*2) + for oldID, data := range subs { var old v0_0_0.SubscriptionResource if err := json.Unmarshal(data.Attributes, &old); err != nil { return fmt.Errorf("failed to unmarshal old subscription resource: %w", err) @@ -350,7 +377,18 @@ func (v *Version_1_0_0) migrateSubscriptionResources(state *resource.State, para Error: data.Error, TypeDependencies: data.TypeDependencies, }) - delete(resources, oldID) + // We're checking both identifier versions here so that we're not + // dependent on the order of migration calls. + _, v0SlotExists := slots[v0_0_0.ReplicationSlotResourceIdentifier(new.ProviderNode, new.SubscriberNode).ID] + _, v1SlotExists := slots[v1_0_0.ReplicationSlotResourceIdentifier(new.ProviderNode, new.SubscriberNode, new.DatabaseName).ID] + if !v0SlotExists && !v1SlotExists { + slot, err := v.newReplicationSlotResource(new) + if err != nil { + return err + } + adds = append(adds, slot) + } + delete(subs, oldID) } state.Add(adds...) diff --git a/server/internal/resource/migrations/1_0_0_test.go b/server/internal/resource/migrations/1_0_0_test.go index 703880a2..75bd4bfd 100644 --- a/server/internal/resource/migrations/1_0_0_test.go +++ b/server/internal/resource/migrations/1_0_0_test.go @@ -63,6 +63,25 @@ func TestVersion_1_0_0(t *testing.T) { v0_0_0_subscriptionResource(t, "n3", "n2"), }, }, + { + // Databases created before v0.7.0 will not have replication slot + // resources. + name: "three nodes without slots", + in: []*resource.ResourceData{ + v0_0_0_node(t, "n1", "instance-1"), + v0_0_0_node(t, "n2", "instance-2"), + v0_0_0_node(t, "n3", "instance-3"), + v0_0_0_instance(t, "instance-1", "host-1", "n1"), + v0_0_0_instance(t, "instance-2", "host-2", "n2"), + v0_0_0_instance(t, "instance-3", "host-3", "n3"), + v0_0_0_subscriptionResource(t, "n1", "n2"), + v0_0_0_subscriptionResource(t, "n1", "n3"), + v0_0_0_subscriptionResource(t, "n2", "n1"), + v0_0_0_subscriptionResource(t, "n2", "n3"), + v0_0_0_subscriptionResource(t, "n3", "n1"), + v0_0_0_subscriptionResource(t, "n3", "n2"), + }, + }, { // This is what it would look like if we were to migrate a state // while it's partway through an "add node" operation diff --git a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/populate_n3_with_n1_source.json b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/populate_n3_with_n1_source.json index d5160a8e..1b55efc5 100644 --- a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/populate_n3_with_n1_source.json +++ b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/populate_n3_with_n1_source.json @@ -252,6 +252,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n1", "database_name": "test", "owner": "admin", @@ -282,6 +283,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n2", "database_name": "test", "owner": "admin", @@ -312,6 +314,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n3", "database_name": "test", "owner": "admin", diff --git a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/single_node_with_replicas.json b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/single_node_with_replicas.json index 771f8f26..0ab6db41 100644 --- a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/single_node_with_replicas.json +++ b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/single_node_with_replicas.json @@ -161,6 +161,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n1", "database_name": "test", "owner": "admin", diff --git a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes.json b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes.json index 04886b72..5f002184 100644 --- a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes.json +++ b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes.json @@ -209,6 +209,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n1", "database_name": "test", "owner": "admin", @@ -239,6 +240,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n2", "database_name": "test", "owner": "admin", @@ -269,6 +271,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n3", "database_name": "test", "owner": "admin", diff --git a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes_without_slots.json b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes_without_slots.json new file mode 100644 index 00000000..5f002184 --- /dev/null +++ b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/three_nodes_without_slots.json @@ -0,0 +1,702 @@ +{ + "version": "1.0.0", + "resources": { + "database.instance": { + "instance-1": { + "needs_recreate": false, + "executor": { + "type": "host", + "id": "host-1" + }, + "identifier": { + "id": "instance-1", + "type": "database.instance" + }, + "attributes": { + "spec": { + "database_id": "database-1", + "database_name": "test", + "database_users": [ + { + "db_owner": true, + "username": "admin" + } + ], + "host_id": "host-1", + "instance_id": "instance-1", + "node_name": "n1" + } + }, + "dependencies": null, + "type_dependencies": null, + "diff_ignore": [ + "/primary_instance_id", + "/connection_info" + ], + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "instance-2": { + "needs_recreate": false, + "executor": { + "type": "host", + "id": "host-2" + }, + "identifier": { + "id": "instance-2", + "type": "database.instance" + }, + "attributes": { + "spec": { + "database_id": "database-1", + "database_name": "test", + "database_users": [ + { + "db_owner": true, + "username": "admin" + } + ], + "host_id": "host-2", + "instance_id": "instance-2", + "node_name": "n2" + } + }, + "dependencies": null, + "type_dependencies": null, + "diff_ignore": [ + "/primary_instance_id", + "/connection_info" + ], + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "instance-3": { + "needs_recreate": false, + "executor": { + "type": "host", + "id": "host-3" + }, + "identifier": { + "id": "instance-3", + "type": "database.instance" + }, + "attributes": { + "spec": { + "database_id": "database-1", + "database_name": "test", + "database_users": [ + { + "db_owner": true, + "username": "admin" + } + ], + "host_id": "host-3", + "instance_id": "instance-3", + "node_name": "n3" + } + }, + "dependencies": null, + "type_dependencies": null, + "diff_ignore": [ + "/primary_instance_id", + "/connection_info" + ], + "resource_version": "1", + "pending_deletion": false, + "error": "" + } + }, + "database.node": { + "n1": { + "needs_recreate": false, + "executor": { + "type": "any", + "id": "" + }, + "identifier": { + "id": "n1", + "type": "database.node" + }, + "attributes": { + "name": "n1", + "instance_ids": [ + "instance-1" + ], + "primary_instance_id": "instance-1" + }, + "dependencies": [ + { + "id": "instance-1", + "type": "database.instance" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2": { + "needs_recreate": false, + "executor": { + "type": "any", + "id": "" + }, + "identifier": { + "id": "n2", + "type": "database.node" + }, + "attributes": { + "name": "n2", + "instance_ids": [ + "instance-2" + ], + "primary_instance_id": "instance-2" + }, + "dependencies": [ + { + "id": "instance-2", + "type": "database.instance" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3": { + "needs_recreate": false, + "executor": { + "type": "any", + "id": "" + }, + "identifier": { + "id": "n3", + "type": "database.node" + }, + "attributes": { + "name": "n3", + "instance_ids": [ + "instance-3" + ], + "primary_instance_id": "instance-3" + }, + "dependencies": [ + { + "id": "instance-3", + "type": "database.instance" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + } + }, + "database.postgres_database": { + "n1:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n1" + }, + "identifier": { + "id": "n1:test", + "type": "database.postgres_database" + }, + "attributes": { + "database_id": "database-1", + "node_name": "n1", + "database_name": "test", + "owner": "admin", + "rename_from": "", + "has_restore_config": false, + "extra_dependencies": null + }, + "dependencies": [ + { + "id": "n1", + "type": "database.node" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n2" + }, + "identifier": { + "id": "n2:test", + "type": "database.postgres_database" + }, + "attributes": { + "database_id": "database-1", + "node_name": "n2", + "database_name": "test", + "owner": "admin", + "rename_from": "", + "has_restore_config": false, + "extra_dependencies": null + }, + "dependencies": [ + { + "id": "n2", + "type": "database.node" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n3" + }, + "identifier": { + "id": "n3:test", + "type": "database.postgres_database" + }, + "attributes": { + "database_id": "database-1", + "node_name": "n3", + "database_name": "test", + "owner": "admin", + "rename_from": "", + "has_restore_config": false, + "extra_dependencies": null + }, + "dependencies": [ + { + "id": "n3", + "type": "database.node" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + } + }, + "database.replication_slot": { + "n1:n2:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n1" + }, + "identifier": { + "id": "n1:n2:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n1", + "subscriber_node": "n2" + }, + "dependencies": [ + { + "id": "n1:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n1:n3:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n1" + }, + "identifier": { + "id": "n1:n3:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n1", + "subscriber_node": "n3" + }, + "dependencies": [ + { + "id": "n1:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2:n1:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n2" + }, + "identifier": { + "id": "n2:n1:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n2", + "subscriber_node": "n1" + }, + "dependencies": [ + { + "id": "n2:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2:n3:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n2" + }, + "identifier": { + "id": "n2:n3:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n2", + "subscriber_node": "n3" + }, + "dependencies": [ + { + "id": "n2:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3:n1:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n3" + }, + "identifier": { + "id": "n3:n1:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n3", + "subscriber_node": "n1" + }, + "dependencies": [ + { + "id": "n3:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3:n2:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n3" + }, + "identifier": { + "id": "n3:n2:test", + "type": "database.replication_slot" + }, + "attributes": { + "database_name": "test", + "provider_node": "n3", + "subscriber_node": "n2" + }, + "dependencies": [ + { + "id": "n3:test", + "type": "database.postgres_database" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + } + }, + "database.subscription": { + "n1:n2:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n2" + }, + "identifier": { + "id": "n1:n2:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n2", + "provider_node": "n1", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n2:test", + "type": "database.postgres_database" + }, + { + "id": "n1:test", + "type": "database.postgres_database" + }, + { + "id": "n1:n2:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n1:n3:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n3" + }, + "identifier": { + "id": "n1:n3:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n3", + "provider_node": "n1", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n3:test", + "type": "database.postgres_database" + }, + { + "id": "n1:test", + "type": "database.postgres_database" + }, + { + "id": "n1:n3:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2:n1:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n1" + }, + "identifier": { + "id": "n2:n1:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n1", + "provider_node": "n2", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n1:test", + "type": "database.postgres_database" + }, + { + "id": "n2:test", + "type": "database.postgres_database" + }, + { + "id": "n2:n1:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n2:n3:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n3" + }, + "identifier": { + "id": "n2:n3:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n3", + "provider_node": "n2", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n3:test", + "type": "database.postgres_database" + }, + { + "id": "n2:test", + "type": "database.postgres_database" + }, + { + "id": "n2:n3:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3:n1:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n1" + }, + "identifier": { + "id": "n3:n1:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n1", + "provider_node": "n3", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n1:test", + "type": "database.postgres_database" + }, + { + "id": "n3:test", + "type": "database.postgres_database" + }, + { + "id": "n3:n1:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + }, + "n3:n2:test": { + "needs_recreate": false, + "executor": { + "type": "primary", + "id": "n2" + }, + "identifier": { + "id": "n3:n2:test", + "type": "database.subscription" + }, + "attributes": { + "database_name": "test", + "subscriber_node": "n2", + "provider_node": "n3", + "disabled": false, + "sync_structure": false, + "sync_data": false, + "extra_dependencies": null, + "needs_update": false + }, + "dependencies": [ + { + "id": "n2:test", + "type": "database.postgres_database" + }, + { + "id": "n3:test", + "type": "database.postgres_database" + }, + { + "id": "n3:n2:test", + "type": "database.replication_slot" + } + ], + "type_dependencies": null, + "diff_ignore": null, + "resource_version": "1", + "pending_deletion": false, + "error": "" + } + } + } +} \ No newline at end of file diff --git a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/with_restore_config.json b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/with_restore_config.json index 9fe553bb..a28db611 100644 --- a/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/with_restore_config.json +++ b/server/internal/resource/migrations/golden_test/TestVersion_1_0_0/with_restore_config.json @@ -86,6 +86,7 @@ "type": "database.postgres_database" }, "attributes": { + "database_id": "database-1", "node_name": "n1", "database_name": "test", "owner": "admin", diff --git a/server/internal/resource/migrations/schemas/v1_0_0/database.go b/server/internal/resource/migrations/schemas/v1_0_0/database.go index bcef0678..f54fb00d 100644 --- a/server/internal/resource/migrations/schemas/v1_0_0/database.go +++ b/server/internal/resource/migrations/schemas/v1_0_0/database.go @@ -1,4 +1,4 @@ -// produced by schematool ceff237ed3d249af64e61b8343cc37c859f17ac2 server/internal/database InstanceResource LagTrackerCommitTimestampResource PostgresDatabaseResource ReplicationSlotAdvanceFromCTSResource ReplicationSlotCreateResource ReplicationSlotResource SubscriptionResource SyncEventResource WaitForSyncEventResource +// produced by schematool d9a1e0f9656f56130752f6c62ede08acfb3fe9bd server/internal/database InstanceResource LagTrackerCommitTimestampResource PostgresDatabaseResource ReplicationSlotAdvanceFromCTSResource ReplicationSlotCreateResource ReplicationSlotResource SubscriptionResource SyncEventResource WaitForSyncEventResource package v1_0_0 import ( @@ -108,7 +108,8 @@ type InstanceResource struct { ExtraLabels map[string]string `json:"extra_labels,omitempty"` } `json:"docker,omitempty"` } `json:"orchestrator_opts,omitempty"` - InPlaceRestore bool `json:"in_place_restore,omitempty"` + InPlaceRestore bool `json:"in_place_restore,omitempty"` + AllHostIDs []string `json:"all_host_ids"` } `json:"spec"` InstanceHostname string `json:"instance_hostname"` PrimaryInstanceID string `json:"primary_instance_id"` @@ -129,6 +130,14 @@ type InstanceResource struct { ClientPort int InstanceHostname string } `json:"connection_info"` + PostInit *struct { + DatabaseID string `json:"database_id"` + NodeName string `json:"node_name"` + Name string `json:"name"` + Statements []string `json:"statements"` + Succeeded bool `json:"succeeded"` + NeedsToRun bool `json:"needs_to_run"` + } `json:"post_init"` } const ResourceTypeLagTrackerCommitTS resource.Type = "database.lag_tracker_commit_ts" @@ -161,6 +170,7 @@ func PostgresDatabaseResourceIdentifier(nodeName, dbName string) resource.Identi } type PostgresDatabaseResource struct { + DatabaseID string `json:"database_id"` NodeName string `json:"node_name"` DatabaseName string `json:"database_name"` Owner string `json:"owner"` @@ -170,6 +180,14 @@ type PostgresDatabaseResource struct { ID string `json:"id"` Type string `json:"type"` } `json:"extra_dependencies"` + PostDatabaseCreate *struct { + DatabaseID string `json:"database_id"` + NodeName string `json:"node_name"` + Name string `json:"name"` + Statements []string `json:"statements"` + Succeeded bool `json:"succeeded"` + NeedsToRun bool `json:"needs_to_run"` + } `json:"post_database_create,omitempty"` } const ResourceTypeReplicationSlotAdvanceFromCTS resource.Type = "database.replication_slot_advance_from_cts"