Skip to content

Commit 1525a3f

Browse files
authored
[Backport 2.x] Split the remote global metadata file to metadata attribute files (opensearch-project#13703)
* Split the remote global metadata file to metadata attribute files (opensearch-project#12190) * Split the cluster state remote global metadata file to metadata attribute files Signed-off-by: Shivansh Arora <[email protected]> (cherry picked from commit da3ab92) * Remove conflicting static method from Metadata.Custom interface Signed-off-by: Shivansh Arora <[email protected]> --------- Signed-off-by: Shivansh Arora <[email protected]>
1 parent 8b62948 commit 1525a3f

File tree

11 files changed

+1878
-420
lines changed

11 files changed

+1878
-420
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.upgrades;
10+
11+
import org.opensearch.client.Request;
12+
import org.opensearch.client.Response;
13+
14+
import java.util.Map;
15+
16+
public class ClusterStateIT extends AbstractRollingTestCase{
17+
public void testTemplateMetadataUpgrades() throws Exception {
18+
if (CLUSTER_TYPE == ClusterType.OLD) {
19+
String templateName = "my_template";
20+
Request putIndexTemplate = new Request("PUT", "_template/" + templateName);
21+
putIndexTemplate.setJsonEntity("{\"index_patterns\": [\"pattern-1\", \"log-*\"]}");
22+
client().performRequest(putIndexTemplate);
23+
verifyTemplateMetadataInClusterState();
24+
} else {
25+
verifyTemplateMetadataInClusterState();
26+
}
27+
}
28+
29+
@SuppressWarnings("unchecked")
30+
private static void verifyTemplateMetadataInClusterState() throws Exception {
31+
Request request = new Request("GET", "_cluster/state/metadata");
32+
Response response = client().performRequest(request);
33+
assertOK(response);
34+
Map<String, Object> metadata = (Map<String, Object>) entityAsMap(response).get("metadata");
35+
assertNotNull(metadata.get("templates"));
36+
}
37+
}

server/src/internalClusterTest/java/org/opensearch/gateway/remote/RemoteClusterStateServiceIT.java

+47
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,21 @@
2020
import org.opensearch.test.OpenSearchIntegTestCase;
2121
import org.junit.Before;
2222

23+
import java.io.IOException;
2324
import java.nio.charset.StandardCharsets;
2425
import java.util.Base64;
2526
import java.util.Map;
27+
import java.util.function.Function;
2628
import java.util.stream.Collectors;
2729

2830
import static org.opensearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS;
31+
import static org.opensearch.gateway.remote.RemoteClusterStateService.COORDINATION_METADATA;
32+
import static org.opensearch.gateway.remote.RemoteClusterStateService.CUSTOM_METADATA;
33+
import static org.opensearch.gateway.remote.RemoteClusterStateService.DELIMITER;
34+
import static org.opensearch.gateway.remote.RemoteClusterStateService.METADATA_FILE_PREFIX;
2935
import static org.opensearch.gateway.remote.RemoteClusterStateService.REMOTE_CLUSTER_STATE_ENABLED_SETTING;
36+
import static org.opensearch.gateway.remote.RemoteClusterStateService.SETTING_METADATA;
37+
import static org.opensearch.gateway.remote.RemoteClusterStateService.TEMPLATES_METADATA;
3038

3139
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0)
3240
public class RemoteClusterStateServiceIT extends RemoteStoreBaseIntegTestCase {
@@ -187,6 +195,45 @@ public void testRemoteStateStatsFromAllNodes() {
187195
}
188196
}
189197

198+
public void testRemoteClusterStateMetadataSplit() throws IOException {
199+
initialTestSetup(1, 0, 1, 1);
200+
201+
RemoteClusterStateService remoteClusterStateService = internalCluster().getClusterManagerNodeInstance(
202+
RemoteClusterStateService.class
203+
);
204+
RepositoriesService repositoriesService = internalCluster().getClusterManagerNodeInstance(RepositoriesService.class);
205+
BlobStoreRepository repository = (BlobStoreRepository) repositoriesService.repository(REPOSITORY_NAME);
206+
BlobPath globalMetadataPath = repository.basePath()
207+
.add(
208+
Base64.getUrlEncoder()
209+
.withoutPadding()
210+
.encodeToString(getClusterState().getClusterName().value().getBytes(StandardCharsets.UTF_8))
211+
)
212+
.add("cluster-state")
213+
.add(getClusterState().metadata().clusterUUID())
214+
.add("global-metadata");
215+
216+
Map<String, Integer> metadataFiles = repository.blobStore()
217+
.blobContainer(globalMetadataPath)
218+
.listBlobs()
219+
.keySet()
220+
.stream()
221+
.map(fileName -> {
222+
logger.info(fileName);
223+
return fileName.split(DELIMITER)[0];
224+
})
225+
.collect(Collectors.toMap(Function.identity(), key -> 1, Integer::sum));
226+
227+
assertTrue(metadataFiles.containsKey(COORDINATION_METADATA));
228+
assertEquals(1, (int) metadataFiles.get(COORDINATION_METADATA));
229+
assertTrue(metadataFiles.containsKey(SETTING_METADATA));
230+
assertEquals(1, (int) metadataFiles.get(SETTING_METADATA));
231+
assertTrue(metadataFiles.containsKey(TEMPLATES_METADATA));
232+
assertEquals(1, (int) metadataFiles.get(TEMPLATES_METADATA));
233+
assertTrue(metadataFiles.keySet().stream().anyMatch(key -> key.startsWith(CUSTOM_METADATA)));
234+
assertFalse(metadataFiles.containsKey(METADATA_FILE_PREFIX));
235+
}
236+
190237
private void validateNodesStatsResponse(NodesStatsResponse nodesStatsResponse) {
191238
// _nodes/stats/discovery must never fail due to any exception
192239
assertFalse(nodesStatsResponse.toString().contains("exception"));

server/src/internalClusterTest/java/org/opensearch/remotestore/RemoteStoreClusterStateRestoreIT.java

+78-1
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,30 @@
88

99
package org.opensearch.remotestore;
1010

11+
import org.opensearch.action.admin.cluster.configuration.AddVotingConfigExclusionsAction;
12+
import org.opensearch.action.admin.cluster.configuration.AddVotingConfigExclusionsRequest;
1113
import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
14+
import org.opensearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
15+
import org.opensearch.action.admin.indices.alias.Alias;
1216
import org.opensearch.action.admin.indices.datastream.DataStreamRolloverIT;
1317
import org.opensearch.action.admin.indices.settings.put.UpdateSettingsRequest;
18+
import org.opensearch.action.admin.indices.template.put.PutComponentTemplateAction;
19+
import org.opensearch.action.admin.indices.template.put.PutComposableIndexTemplateAction;
1420
import org.opensearch.action.admin.indices.template.put.PutIndexTemplateRequest;
21+
import org.opensearch.action.support.master.AcknowledgedResponse;
1522
import org.opensearch.cluster.ClusterState;
1623
import org.opensearch.cluster.block.ClusterBlockException;
24+
import org.opensearch.cluster.metadata.ComponentTemplate;
25+
import org.opensearch.cluster.metadata.ComponentTemplateMetadata;
26+
import org.opensearch.cluster.metadata.ComposableIndexTemplate;
27+
import org.opensearch.cluster.metadata.ComposableIndexTemplateMetadata;
1728
import org.opensearch.cluster.metadata.IndexMetadata;
1829
import org.opensearch.cluster.metadata.IndexTemplateMetadata;
1930
import org.opensearch.cluster.metadata.Metadata;
2031
import org.opensearch.cluster.metadata.RepositoriesMetadata;
32+
import org.opensearch.cluster.metadata.Template;
33+
import org.opensearch.common.action.ActionFuture;
34+
import org.opensearch.common.settings.Setting;
2135
import org.opensearch.common.settings.Settings;
2236
import org.opensearch.gateway.remote.ClusterMetadataManifest;
2337
import org.opensearch.gateway.remote.ClusterMetadataManifest.UploadedIndexMetadata;
@@ -30,11 +44,13 @@
3044
import java.nio.file.Files;
3145
import java.nio.file.Path;
3246
import java.util.Arrays;
47+
import java.util.Collections;
3348
import java.util.List;
3449
import java.util.Locale;
3550
import java.util.Map;
3651
import java.util.Objects;
3752
import java.util.concurrent.ExecutionException;
53+
import java.util.stream.Collectors;
3854

3955
import static org.opensearch.cluster.coordination.ClusterBootstrapService.INITIAL_CLUSTER_MANAGER_NODES_SETTING;
4056
import static org.opensearch.cluster.metadata.IndexMetadata.INDEX_READ_ONLY_SETTING;
@@ -47,6 +63,11 @@
4763

4864
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0)
4965
public class RemoteStoreClusterStateRestoreIT extends BaseRemoteStoreRestoreIT {
66+
static final String TEMPLATE_NAME = "remote-store-test-template";
67+
static final String COMPONENT_TEMPLATE_NAME = "remote-component-template1";
68+
static final String COMPOSABLE_TEMPLATE_NAME = "remote-composable-template1";
69+
static final Setting<String> MOCK_SETTING = Setting.simpleString("mock-setting");
70+
static final String[] EXCLUDED_NODES = { "ex-1", "ex-2" };
5071

5172
@Before
5273
public void setup() {
@@ -93,6 +114,45 @@ public void testFullClusterRestore() throws Exception {
93114
Map<String, Long> indexStats = initialTestSetup(shardCount, replicaCount, dataNodeCount, 1);
94115
String prevClusterUUID = clusterService().state().metadata().clusterUUID();
95116
long prevClusterStateVersion = clusterService().state().version();
117+
// Step - 1.1 Add some cluster state elements
118+
ActionFuture<AcknowledgedResponse> response = client().admin()
119+
.indices()
120+
.preparePutTemplate(TEMPLATE_NAME)
121+
.addAlias(new Alias(INDEX_NAME))
122+
.setPatterns(Arrays.stream(INDEX_NAMES_WILDCARD.split(",")).collect(Collectors.toList()))
123+
.execute();
124+
assertTrue(response.get().isAcknowledged());
125+
ActionFuture<ClusterUpdateSettingsResponse> clusterUpdateSettingsResponse = client().admin()
126+
.cluster()
127+
.prepareUpdateSettings()
128+
.setPersistentSettings(Settings.builder().put(SETTING_READ_ONLY_SETTING.getKey(), false).build())
129+
.execute();
130+
assertTrue(clusterUpdateSettingsResponse.get().isAcknowledged());
131+
// update coordination metadata
132+
client().execute(AddVotingConfigExclusionsAction.INSTANCE, new AddVotingConfigExclusionsRequest(EXCLUDED_NODES));
133+
// Add a custom metadata as component index template
134+
ActionFuture<AcknowledgedResponse> componentTemplateResponse = client().execute(
135+
PutComponentTemplateAction.INSTANCE,
136+
new PutComponentTemplateAction.Request(COMPONENT_TEMPLATE_NAME).componentTemplate(
137+
new ComponentTemplate(new Template(Settings.EMPTY, null, Collections.emptyMap()), 1L, Collections.emptyMap())
138+
)
139+
);
140+
assertTrue(componentTemplateResponse.get().isAcknowledged());
141+
ActionFuture<AcknowledgedResponse> composableTemplateResponse = client().execute(
142+
PutComposableIndexTemplateAction.INSTANCE,
143+
new PutComposableIndexTemplateAction.Request(COMPOSABLE_TEMPLATE_NAME).indexTemplate(
144+
new ComposableIndexTemplate(
145+
Arrays.stream(INDEX_NAMES_WILDCARD.split(",")).collect(Collectors.toList()),
146+
new Template(Settings.EMPTY, null, Collections.emptyMap()),
147+
Collections.singletonList(COMPONENT_TEMPLATE_NAME),
148+
1L,
149+
1L,
150+
Collections.emptyMap(),
151+
null
152+
)
153+
)
154+
);
155+
assertTrue(composableTemplateResponse.get().isAcknowledged());
96156

97157
// Step - 2 Replace all nodes in the cluster with new nodes. This ensures new cluster state doesn't have previous index metadata
98158
resetCluster(dataNodeCount, clusterManagerNodeCount);
@@ -110,7 +170,24 @@ public void testFullClusterRestore() throws Exception {
110170
);
111171
validateMetadata(List.of(INDEX_NAME));
112172
verifyRedIndicesAndTriggerRestore(indexStats, INDEX_NAME, true);
113-
173+
clusterService().state()
174+
.metadata()
175+
.coordinationMetadata()
176+
.getVotingConfigExclusions()
177+
.stream()
178+
.forEach(config -> assertTrue(Arrays.stream(EXCLUDED_NODES).anyMatch(node -> node.equals(config.getNodeId()))));
179+
assertFalse(clusterService().state().metadata().templates().isEmpty());
180+
assertTrue(clusterService().state().metadata().templates().containsKey(TEMPLATE_NAME));
181+
assertFalse(clusterService().state().metadata().settings().isEmpty());
182+
assertFalse(clusterService().state().metadata().settings().getAsBoolean(SETTING_READ_ONLY_SETTING.getKey(), true));
183+
assertNotNull(clusterService().state().metadata().custom("component_template"));
184+
ComponentTemplateMetadata componentTemplateMetadata = clusterService().state().metadata().custom("component_template");
185+
assertFalse(componentTemplateMetadata.componentTemplates().isEmpty());
186+
assertTrue(componentTemplateMetadata.componentTemplates().containsKey(COMPONENT_TEMPLATE_NAME));
187+
assertNotNull(clusterService().state().metadata().custom("index_template"));
188+
ComposableIndexTemplateMetadata composableIndexTemplate = clusterService().state().metadata().custom("index_template");
189+
assertFalse(composableIndexTemplate.indexTemplates().isEmpty());
190+
assertTrue(composableIndexTemplate.indexTemplates().containsKey(COMPOSABLE_TEMPLATE_NAME));
114191
}
115192

116193
/**

0 commit comments

Comments
 (0)