diff --git a/managed/src/main/java/com/yugabyte/yw/commissioner/tasks/UniverseTaskBase.java b/managed/src/main/java/com/yugabyte/yw/commissioner/tasks/UniverseTaskBase.java index f7a7169bb7a..ac6fbd49cde 100644 --- a/managed/src/main/java/com/yugabyte/yw/commissioner/tasks/UniverseTaskBase.java +++ b/managed/src/main/java/com/yugabyte/yw/commissioner/tasks/UniverseTaskBase.java @@ -5951,7 +5951,8 @@ protected void createDeleteXClusterConfigSubtasks( && pitrConfig .getUniverse() .getUniverseUUID() - .equals(xClusterConfig.getSourceUniverseUUID())) + .equals(xClusterConfig.getSourceUniverseUUID()) + && pitrConfig.getXClusterConfigs().size() <= 1) || (deleteTargetPitrConfigs && pitrConfig .getUniverse() diff --git a/managed/src/main/java/com/yugabyte/yw/models/PitrConfig.java b/managed/src/main/java/com/yugabyte/yw/models/PitrConfig.java index 04e8b2c5920..930ff1ee99f 100644 --- a/managed/src/main/java/com/yugabyte/yw/models/PitrConfig.java +++ b/managed/src/main/java/com/yugabyte/yw/models/PitrConfig.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.yugabyte.yw.common.PlatformServiceException; import com.yugabyte.yw.forms.CreatePitrConfigParams; @@ -27,6 +28,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -161,4 +163,13 @@ public boolean isUsedForXCluster() { List sqlRow = DB.sqlQuery(sqlStatement).setParameter("pitrUuid", this.uuid).findList(); return !sqlRow.isEmpty(); } + + @JsonIgnore + public List getXClusterConfigs() { + String sqlStatement = "SELECT xcluster_uuid FROM xcluster_pitr WHERE pitr_uuid = :pitrUuid"; + List sqlRow = DB.sqlQuery(sqlStatement).setParameter("pitrUuid", this.uuid).findList(); + return sqlRow.stream() + .map(row -> XClusterConfig.getOrBadRequest(UUID.fromString(row.getString("xcluster_uuid")))) + .collect(Collectors.toList()); + } } diff --git a/managed/src/test/java/com/yugabyte/yw/models/PitrConfigTest.java b/managed/src/test/java/com/yugabyte/yw/models/PitrConfigTest.java new file mode 100644 index 00000000000..4eefd6bf3f7 --- /dev/null +++ b/managed/src/test/java/com/yugabyte/yw/models/PitrConfigTest.java @@ -0,0 +1,103 @@ +// Copyright (c) YugaByte, Inc. +package com.yugabyte.yw.models; + +import static com.yugabyte.yw.common.ModelFactory.createUniverse; +import static org.junit.Assert.assertEquals; + +import com.fasterxml.jackson.databind.JsonNode; +import com.yugabyte.yw.common.FakeDBApplication; +import com.yugabyte.yw.common.ModelFactory; +import com.yugabyte.yw.forms.CreatePitrConfigParams; +import com.yugabyte.yw.forms.DrConfigCreateForm.PitrParams; +import com.yugabyte.yw.forms.XClusterConfigCreateFormData.BootstrapParams.BootstrapBackupParams; +import com.yugabyte.yw.models.configs.CustomerConfig; +import java.util.Set; +import java.util.UUID; +import org.junit.Before; +import org.junit.Test; +import org.yb.CommonTypes.TableType; +import play.libs.Json; + +public class PitrConfigTest extends FakeDBApplication { + + private CustomerConfig config; + + @Before + public void setUp() { + Customer defaultCustomer = ModelFactory.testCustomer(); + config = createData(defaultCustomer); + } + + private CustomerConfig createData(Customer customer) { + JsonNode formData = + Json.parse( + "{\"name\": \"Test\", \"configName\": \"Test\", \"type\": " + + "\"STORAGE\", \"data\": {\"foo\": \"bar\"}," + + "\"configUUID\": \"5e8e4887-343b-47dd-a126-71c822904c06\"}"); + return CustomerConfig.createWithFormData(customer.getUuid(), formData); + } + + @Test + public void testPitrConfigXClusterCount() { + + Universe sourceUniverse = createUniverse("source Universe"); + Universe targetUniverse = createUniverse("target Universe"); + + BootstrapBackupParams backupRequestParams; + backupRequestParams = new BootstrapBackupParams(); + backupRequestParams.storageConfigUUID = config.getConfigUUID(); + + Set sourceDbIds = Set.of("db1", "db2"); + DrConfig drConfig1 = + DrConfig.create( + "replication1", + sourceUniverse.getUniverseUUID(), + targetUniverse.getUniverseUUID(), + backupRequestParams, + new PitrParams(), + sourceDbIds); + XClusterConfig xClusterConfig1 = drConfig1.getActiveXClusterConfig(); + + CreatePitrConfigParams createPitrConfigParams = new CreatePitrConfigParams(); + createPitrConfigParams.setUniverseUUID(sourceUniverse.getUniverseUUID()); + createPitrConfigParams.customerUUID = Customer.get(sourceUniverse.getCustomerId()).getUuid(); + createPitrConfigParams.name = null; + createPitrConfigParams.keyspaceName = "mockNamespace"; + createPitrConfigParams.tableType = TableType.PGSQL_TABLE_TYPE; + createPitrConfigParams.retentionPeriodInSeconds = 1; + createPitrConfigParams.xClusterConfig = xClusterConfig1; + createPitrConfigParams.intervalInSeconds = 1; + createPitrConfigParams.createdForDr = true; + + PitrConfig pitrConfig = PitrConfig.create(UUID.randomUUID(), createPitrConfigParams); + xClusterConfig1.addPitrConfig(pitrConfig); + pitrConfig.refresh(); + + assertEquals(1, pitrConfig.getXClusterConfigs().size()); + assertEquals(xClusterConfig1.getUuid(), pitrConfig.getXClusterConfigs().get(0).getUuid()); + + Universe secondTargetUniverse = createUniverse("second target Universe"); + // A -> B and A -> C. + DrConfig drConfig2 = + DrConfig.create( + "replication2", + sourceUniverse.getUniverseUUID(), + secondTargetUniverse.getUniverseUUID(), + backupRequestParams, + new PitrParams(), + sourceDbIds); + XClusterConfig xClusterConfig2 = drConfig2.getActiveXClusterConfig(); + xClusterConfig2.addPitrConfig(pitrConfig); + + // Pitr Config is associated to 2 xcluster configs. + pitrConfig.refresh(); + assertEquals(2, pitrConfig.getXClusterConfigs().size()); + assertEquals(xClusterConfig2.getUuid(), pitrConfig.getXClusterConfigs().get(1).getUuid()); + + // xcluster_pitr should be cascade deleted when xcluster config is deleted. + xClusterConfig2.delete(); + pitrConfig.refresh(); + assertEquals(1, pitrConfig.getXClusterConfigs().size()); + assertEquals(xClusterConfig1.getUuid(), pitrConfig.getXClusterConfigs().get(0).getUuid()); + } +}