Skip to content

Commit 979fd05

Browse files
[test][controller] Fix multi-region tests to use VeniceTwoLayerMultiRegionMultiClusterWrapper (#1067)
There are several tests that create multi-region clusters through manual, non-standard setups. An example of this is that many tests create a multi-region cluster that shares the same Kafka cluster between them. While this might be valuable for some tests, it is a maintenance overhead for most of them. Our test suite already has "VeniceTwoLayerMultiRegionMultiClusterWrapper" that can be used directly for all current use-cases. This commit replaces all tests that setup a multi-region test cluster through non-standard means to use "VeniceTwoLayerMultiRegionMultiClusterWrapper" instead. This commit also fixes an issue where if the config to enable active active by default for batch-only stores is enabled, new store creation for system stores makes them also active-active. This was masked previously by different configs set on child and parent controllers. So, running this config in parent controller would have been problematic. This change exposed another bug that storage persona only runs validations when running in a multi-region setups while there is nothing conceptually blocking it from running in a single-region setup. This will be addressed in a follow up PR.
1 parent a14900c commit 979fd05

28 files changed

+1696
-1386
lines changed

internal/venice-test-common/src/integrationTest/java/com/linkedin/venice/controller/TestClusterLevelConfigForActiveActiveReplication.java

Lines changed: 166 additions & 212 deletions
Large diffs are not rendered by default.

internal/venice-test-common/src/integrationTest/java/com/linkedin/venice/controller/TestClusterLevelConfigForNativeReplication.java

Lines changed: 74 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,108 +3,101 @@
33
import static com.linkedin.venice.ConfigKeys.ENABLE_NATIVE_REPLICATION_AS_DEFAULT_FOR_BATCH_ONLY;
44
import static com.linkedin.venice.ConfigKeys.NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_BATCH_ONLY_STORES;
55
import static com.linkedin.venice.ConfigKeys.NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_HYBRID_STORES;
6-
import static com.linkedin.venice.controller.VeniceHelixAdmin.VERSION_ID_UNSET;
7-
import static org.mockito.ArgumentMatchers.any;
8-
import static org.mockito.ArgumentMatchers.anyString;
9-
import static org.mockito.Mockito.doReturn;
10-
import static org.mockito.Mockito.mock;
6+
import static com.linkedin.venice.utils.TestUtils.assertCommand;
7+
import static org.testng.Assert.assertEquals;
8+
import static org.testng.Assert.assertTrue;
119

10+
import com.linkedin.venice.controllerapi.ControllerClient;
1211
import com.linkedin.venice.controllerapi.UpdateStoreQueryParams;
13-
import com.linkedin.venice.meta.Version;
14-
import com.linkedin.venice.pubsub.manager.TopicManager;
15-
import com.linkedin.venice.pubsub.manager.TopicManagerRepository;
12+
import com.linkedin.venice.integration.utils.ServiceFactory;
13+
import com.linkedin.venice.integration.utils.VeniceMultiRegionClusterCreateOptions;
14+
import com.linkedin.venice.integration.utils.VeniceTwoLayerMultiRegionMultiClusterWrapper;
15+
import com.linkedin.venice.meta.StoreInfo;
16+
import com.linkedin.venice.utils.TestUtils;
17+
import com.linkedin.venice.utils.Time;
1618
import com.linkedin.venice.utils.Utils;
17-
import java.io.IOException;
18-
import java.util.Optional;
1919
import java.util.Properties;
20+
import java.util.concurrent.TimeUnit;
2021
import org.testng.Assert;
2122
import org.testng.annotations.AfterClass;
2223
import org.testng.annotations.BeforeClass;
2324
import org.testng.annotations.Test;
2425

2526

26-
public class TestClusterLevelConfigForNativeReplication extends AbstractTestVeniceHelixAdmin {
27+
public class TestClusterLevelConfigForNativeReplication {
28+
private static final long TEST_TIMEOUT = 60 * Time.MS_PER_SECOND;
29+
30+
private VeniceTwoLayerMultiRegionMultiClusterWrapper multiRegionMultiClusterWrapper;
31+
private ControllerClient parentControllerClient;
32+
2733
@BeforeClass(alwaysRun = true)
28-
public void setUp() throws Exception {
29-
setupCluster();
34+
public void setUp() {
35+
Utils.thisIsLocalhost();
36+
Properties parentControllerProps = new Properties();
37+
// enable native replication for batch-only stores through cluster-level config
38+
parentControllerProps.setProperty(ENABLE_NATIVE_REPLICATION_AS_DEFAULT_FOR_BATCH_ONLY, "true");
39+
parentControllerProps.setProperty(NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_BATCH_ONLY_STORES, "dc-batch");
40+
parentControllerProps.setProperty(NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_HYBRID_STORES, "dc-hybrid");
41+
multiRegionMultiClusterWrapper = ServiceFactory.getVeniceTwoLayerMultiRegionMultiClusterWrapper(
42+
new VeniceMultiRegionClusterCreateOptions.Builder().numberOfRegions(1)
43+
.numberOfParentControllers(1)
44+
.numberOfChildControllers(1)
45+
.numberOfRouters(1)
46+
.numberOfServers(1)
47+
.parentControllerProperties(parentControllerProps)
48+
.build());
49+
parentControllerClient = new ControllerClient(
50+
multiRegionMultiClusterWrapper.getClusterNames()[0],
51+
multiRegionMultiClusterWrapper.getControllerConnectString());
3052
}
3153

3254
@AfterClass(alwaysRun = true)
33-
public void cleanUp() {
34-
cleanupCluster();
35-
}
36-
37-
@Override
38-
Properties getControllerProperties(String clusterName) throws IOException {
39-
Properties props = super.getControllerProperties(clusterName);
40-
// enable native replication for batch-only stores through cluster-level config
41-
props.setProperty(ENABLE_NATIVE_REPLICATION_AS_DEFAULT_FOR_BATCH_ONLY, "true");
42-
props.setProperty(NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_BATCH_ONLY_STORES, "dc-batch");
43-
props.setProperty(NATIVE_REPLICATION_SOURCE_FABRIC_AS_DEFAULT_FOR_HYBRID_STORES, "dc-hybrid");
44-
return props;
55+
public void tearDown() {
56+
Utils.closeQuietlyWithErrorLogged(parentControllerClient);
57+
Utils.closeQuietlyWithErrorLogged(multiRegionMultiClusterWrapper);
4558
}
4659

47-
@Test
60+
@Test(timeOut = TEST_TIMEOUT)
4861
public void testClusterLevelNativeReplicationConfigForNewStores() {
49-
TopicManagerRepository originalTopicManagerRepository = veniceAdmin.getTopicManagerRepository();
50-
51-
TopicManager mockedTopicManager = mock(TopicManager.class);
52-
TopicManagerRepository mockedTopicManageRepository = mock(TopicManagerRepository.class);
53-
doReturn(mockedTopicManager).when(mockedTopicManageRepository).getLocalTopicManager();
54-
doReturn(mockedTopicManager).when(mockedTopicManageRepository).getTopicManager(any(String.class));
55-
doReturn(mockedTopicManager).when(mockedTopicManageRepository).getTopicManager(anyString());
56-
veniceAdmin.setTopicManagerRepository(mockedTopicManageRepository);
5762
String storeName = Utils.getUniqueString("test-store");
5863
String pushJobId1 = "test-push-job-id-1";
59-
/**
60-
* Do not enable any store-level config for leader/follower mode or native replication feature.
61-
*/
62-
veniceAdmin.createStore(clusterName, storeName, "test-owner", KEY_SCHEMA, VALUE_SCHEMA);
64+
parentControllerClient.createNewStore(storeName, "test-owner", "\"string\"", "\"string\"");
65+
parentControllerClient.emptyPush(storeName, pushJobId1, 1);
6366

64-
/**
65-
* Add a version
66-
*/
67-
veniceAdmin.addVersionAndTopicOnly(
68-
clusterName,
69-
storeName,
70-
pushJobId1,
71-
VERSION_ID_UNSET,
72-
1,
73-
1,
74-
false,
75-
true,
76-
Version.PushType.BATCH,
77-
null,
78-
null,
79-
Optional.empty(),
80-
-1,
81-
1,
82-
Optional.empty(),
83-
false);
8467
// Version 1 should exist.
85-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).getVersions().size(), 1);
68+
StoreInfo store = assertCommand(parentControllerClient.getStore(storeName)).getStore();
69+
assertEquals(store.getVersions().size(), 1);
8670
// native replication should be enabled by cluster-level config
87-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).isNativeReplicationEnabled(), true);
88-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).getNativeReplicationSourceFabric(), "dc-batch");
89-
veniceAdmin.updateStore(
90-
clusterName,
91-
storeName,
92-
new UpdateStoreQueryParams().setHybridRewindSeconds(1L).setHybridOffsetLagThreshold(1L));
93-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).getNativeReplicationSourceFabric(), "dc-hybrid");
94-
veniceAdmin.updateStore(
95-
clusterName,
96-
storeName,
97-
new UpdateStoreQueryParams().setHybridRewindSeconds(-1L).setHybridOffsetLagThreshold(-1L));
98-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).getNativeReplicationSourceFabric(), "dc-batch");
99-
veniceAdmin.updateStore(
100-
clusterName,
101-
storeName,
102-
new UpdateStoreQueryParams().setIncrementalPushEnabled(true)
103-
.setHybridRewindSeconds(1L)
104-
.setHybridOffsetLagThreshold(10));
105-
Assert.assertEquals(veniceAdmin.getStore(clusterName, storeName).getNativeReplicationSourceFabric(), "dc-hybrid");
106-
107-
// Set topic original topic manager back
108-
veniceAdmin.setTopicManagerRepository(originalTopicManagerRepository);
71+
assertTrue(store.isNativeReplicationEnabled());
72+
assertEquals(store.getNativeReplicationSourceFabric(), "dc-batch");
73+
assertCommand(
74+
parentControllerClient.updateStore(
75+
storeName,
76+
new UpdateStoreQueryParams().setHybridRewindSeconds(1L).setHybridOffsetLagThreshold(1L)));
77+
TestUtils.waitForNonDeterministicAssertion(TEST_TIMEOUT, TimeUnit.MILLISECONDS, () -> {
78+
Assert.assertEquals(
79+
parentControllerClient.getStore(storeName).getStore().getNativeReplicationSourceFabric(),
80+
"dc-hybrid");
81+
});
82+
assertCommand(
83+
parentControllerClient.updateStore(
84+
storeName,
85+
new UpdateStoreQueryParams().setHybridRewindSeconds(-1L).setHybridOffsetLagThreshold(-1L)));
86+
TestUtils.waitForNonDeterministicAssertion(TEST_TIMEOUT, TimeUnit.MILLISECONDS, () -> {
87+
Assert.assertEquals(
88+
parentControllerClient.getStore(storeName).getStore().getNativeReplicationSourceFabric(),
89+
"dc-batch");
90+
});
91+
assertCommand(
92+
parentControllerClient.updateStore(
93+
storeName,
94+
new UpdateStoreQueryParams().setIncrementalPushEnabled(true)
95+
.setHybridRewindSeconds(1L)
96+
.setHybridOffsetLagThreshold(10)));
97+
TestUtils.waitForNonDeterministicAssertion(TEST_TIMEOUT, TimeUnit.MILLISECONDS, () -> {
98+
Assert.assertEquals(
99+
parentControllerClient.getStore(storeName).getStore().getNativeReplicationSourceFabric(),
100+
"dc-hybrid");
101+
});
109102
}
110103
}

internal/venice-test-common/src/integrationTest/java/com/linkedin/venice/controller/VeniceParentHelixAdminTest.java

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import static com.linkedin.venice.controller.SchemaConstants.VALUE_SCHEMA_FOR_WRITE_COMPUTE_V3;
1111
import static com.linkedin.venice.controller.SchemaConstants.VALUE_SCHEMA_FOR_WRITE_COMPUTE_V4;
1212
import static com.linkedin.venice.controller.SchemaConstants.VALUE_SCHEMA_FOR_WRITE_COMPUTE_V5;
13-
import static com.linkedin.venice.integration.utils.VeniceClusterWrapperConstants.CHILD_REGION_NAME_PREFIX;
14-
import static com.linkedin.venice.integration.utils.VeniceClusterWrapperConstants.DEFAULT_PARENT_DATA_CENTER_REGION_NAME;
1513
import static com.linkedin.venice.utils.TestUtils.assertCommand;
1614
import static com.linkedin.venice.utils.TestUtils.waitForNonDeterministicAssertion;
1715
import static com.linkedin.venice.utils.TestUtils.waitForNonDeterministicPushCompletion;
@@ -32,14 +30,11 @@
3230
import com.linkedin.venice.controllerapi.StoreResponse;
3331
import com.linkedin.venice.controllerapi.UpdateStoreQueryParams;
3432
import com.linkedin.venice.controllerapi.VersionCreationResponse;
35-
import com.linkedin.venice.integration.utils.PubSubBrokerConfigs;
36-
import com.linkedin.venice.integration.utils.PubSubBrokerWrapper;
3733
import com.linkedin.venice.integration.utils.ServiceFactory;
3834
import com.linkedin.venice.integration.utils.VeniceClusterWrapper;
39-
import com.linkedin.venice.integration.utils.VeniceControllerCreateOptions;
4035
import com.linkedin.venice.integration.utils.VeniceControllerWrapper;
36+
import com.linkedin.venice.integration.utils.VeniceMultiRegionClusterCreateOptions;
4137
import com.linkedin.venice.integration.utils.VeniceTwoLayerMultiRegionMultiClusterWrapper;
42-
import com.linkedin.venice.integration.utils.ZkServerWrapper;
4338
import com.linkedin.venice.meta.ETLStoreConfig;
4439
import com.linkedin.venice.meta.HybridStoreConfig;
4540
import com.linkedin.venice.meta.StoreInfo;
@@ -560,40 +555,33 @@ public static Object[][] controllerSSLAndSupersetSchemaGenerator() {
560555
public void testStoreMetaDataUpdateFromParentToChildController(
561556
boolean isControllerSslEnabled,
562557
boolean isSupersetSchemaGeneratorEnabled) throws IOException {
563-
Properties properties = new Properties();
558+
Properties parentControllerProps = new Properties();
564559
// This cluster setup don't have server, we cannot perform push here.
565-
properties.setProperty(CONTROLLER_AUTO_MATERIALIZE_META_SYSTEM_STORE, String.valueOf(false));
566-
properties.setProperty(CONTROLLER_AUTO_MATERIALIZE_DAVINCI_PUSH_STATUS_SYSTEM_STORE, String.valueOf(false));
560+
parentControllerProps.setProperty(CONTROLLER_AUTO_MATERIALIZE_META_SYSTEM_STORE, String.valueOf(false));
561+
parentControllerProps
562+
.setProperty(CONTROLLER_AUTO_MATERIALIZE_DAVINCI_PUSH_STATUS_SYSTEM_STORE, String.valueOf(false));
567563
if (isSupersetSchemaGeneratorEnabled) {
568-
properties.setProperty(CONTROLLER_PARENT_EXTERNAL_SUPERSET_SCHEMA_GENERATION_ENABLED, String.valueOf(true));
569-
properties.put(
564+
parentControllerProps
565+
.setProperty(CONTROLLER_PARENT_EXTERNAL_SUPERSET_SCHEMA_GENERATION_ENABLED, String.valueOf(true));
566+
parentControllerProps.put(
570567
VeniceControllerWrapper.SUPERSET_SCHEMA_GENERATOR,
571568
new SupersetSchemaGeneratorWithCustomProp("test_prop"));
572569
}
573570

574-
try (ZkServerWrapper zkServer = ServiceFactory.getZkServer();
575-
PubSubBrokerWrapper pubSubBrokerWrapper = ServiceFactory.getPubSubBroker(
576-
new PubSubBrokerConfigs.Builder().setZkWrapper(zkServer)
577-
.setRegionName(DEFAULT_PARENT_DATA_CENTER_REGION_NAME)
578-
.build());
579-
VeniceControllerWrapper childControllerWrapper = ServiceFactory.getVeniceController(
580-
new VeniceControllerCreateOptions.Builder(clusterName, zkServer, pubSubBrokerWrapper)
581-
.sslToKafka(isControllerSslEnabled)
582-
.regionName(CHILD_REGION_NAME_PREFIX + "0")
583-
.build());
584-
ZkServerWrapper parentZk = ServiceFactory.getZkServer();
585-
VeniceControllerWrapper parentControllerWrapper = ServiceFactory.getVeniceController(
586-
new VeniceControllerCreateOptions.Builder(clusterName, parentZk, pubSubBrokerWrapper)
587-
.childControllers(new VeniceControllerWrapper[] { childControllerWrapper })
588-
.extraProperties(properties)
571+
try (VeniceTwoLayerMultiRegionMultiClusterWrapper venice =
572+
ServiceFactory.getVeniceTwoLayerMultiRegionMultiClusterWrapper(
573+
new VeniceMultiRegionClusterCreateOptions.Builder().numberOfRegions(1)
574+
.numberOfClusters(1)
575+
.numberOfParentControllers(1)
576+
.numberOfChildControllers(1)
577+
.numberOfServers(0)
578+
.numberOfRouters(0)
579+
.replicationFactor(1)
580+
.parentControllerProperties(parentControllerProps)
589581
.sslToKafka(isControllerSslEnabled)
590582
.build())) {
591-
String childControllerUrl = isControllerSslEnabled
592-
? childControllerWrapper.getSecureControllerUrl()
593-
: childControllerWrapper.getControllerUrl();
594-
String parentControllerUrl = isControllerSslEnabled
595-
? parentControllerWrapper.getSecureControllerUrl()
596-
: parentControllerWrapper.getControllerUrl();
583+
String childControllerUrl = venice.getChildRegions().get(0).getControllerConnectString();
584+
String parentControllerUrl = venice.getControllerConnectString();
597585
Optional<SSLFactory> sslFactory =
598586
isControllerSslEnabled ? Optional.of(SslUtils.getVeniceLocalSslFactory()) : Optional.empty();
599587
try (ControllerClient parentControllerClient = new ControllerClient(clusterName, parentControllerUrl, sslFactory);

0 commit comments

Comments
 (0)