Skip to content

Commit da3ab92

Browse files
authored
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 <hishiv@amazon.com>
1 parent a9298c9 commit da3ab92

File tree

11 files changed

+1883
-420
lines changed

11 files changed

+1883
-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
@@ -19,13 +19,21 @@
1919
import org.opensearch.repositories.blobstore.BlobStoreRepository;
2020
import org.opensearch.test.OpenSearchIntegTestCase;
2121

22+
import java.io.IOException;
2223
import java.nio.charset.StandardCharsets;
2324
import java.util.Base64;
2425
import java.util.Map;
26+
import java.util.function.Function;
2527
import java.util.stream.Collectors;
2628

2729
import static org.opensearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_REPLICAS;
30+
import static org.opensearch.gateway.remote.RemoteClusterStateService.COORDINATION_METADATA;
31+
import static org.opensearch.gateway.remote.RemoteClusterStateService.CUSTOM_METADATA;
32+
import static org.opensearch.gateway.remote.RemoteClusterStateService.DELIMITER;
33+
import static org.opensearch.gateway.remote.RemoteClusterStateService.METADATA_FILE_PREFIX;
2834
import static org.opensearch.gateway.remote.RemoteClusterStateService.REMOTE_CLUSTER_STATE_ENABLED_SETTING;
35+
import static org.opensearch.gateway.remote.RemoteClusterStateService.SETTING_METADATA;
36+
import static org.opensearch.gateway.remote.RemoteClusterStateService.TEMPLATES_METADATA;
2937

3038
@OpenSearchIntegTestCase.ClusterScope(scope = OpenSearchIntegTestCase.Scope.TEST, numDataNodes = 0)
3139
public class RemoteClusterStateServiceIT extends RemoteStoreBaseIntegTestCase {
@@ -181,6 +189,45 @@ public void testRemoteStateStatsFromAllNodes() {
181189
}
182190
}
183191

192+
public void testRemoteClusterStateMetadataSplit() throws IOException {
193+
initialTestSetup(1, 0, 1, 1);
194+
195+
RemoteClusterStateService remoteClusterStateService = internalCluster().getClusterManagerNodeInstance(
196+
RemoteClusterStateService.class
197+
);
198+
RepositoriesService repositoriesService = internalCluster().getClusterManagerNodeInstance(RepositoriesService.class);
199+
BlobStoreRepository repository = (BlobStoreRepository) repositoriesService.repository(REPOSITORY_NAME);
200+
BlobPath globalMetadataPath = repository.basePath()
201+
.add(
202+
Base64.getUrlEncoder()
203+
.withoutPadding()
204+
.encodeToString(getClusterState().getClusterName().value().getBytes(StandardCharsets.UTF_8))
205+
)
206+
.add("cluster-state")
207+
.add(getClusterState().metadata().clusterUUID())
208+
.add("global-metadata");
209+
210+
Map<String, Integer> metadataFiles = repository.blobStore()
211+
.blobContainer(globalMetadataPath)
212+
.listBlobs()
213+
.keySet()
214+
.stream()
215+
.map(fileName -> {
216+
logger.info(fileName);
217+
return fileName.split(DELIMITER)[0];
218+
})
219+
.collect(Collectors.toMap(Function.identity(), key -> 1, Integer::sum));
220+
221+
assertTrue(metadataFiles.containsKey(COORDINATION_METADATA));
222+
assertEquals(1, (int) metadataFiles.get(COORDINATION_METADATA));
223+
assertTrue(metadataFiles.containsKey(SETTING_METADATA));
224+
assertEquals(1, (int) metadataFiles.get(SETTING_METADATA));
225+
assertTrue(metadataFiles.containsKey(TEMPLATES_METADATA));
226+
assertEquals(1, (int) metadataFiles.get(TEMPLATES_METADATA));
227+
assertTrue(metadataFiles.keySet().stream().anyMatch(key -> key.startsWith(CUSTOM_METADATA)));
228+
assertFalse(metadataFiles.containsKey(METADATA_FILE_PREFIX));
229+
}
230+
184231
private void validateNodesStatsResponse(NodesStatsResponse nodesStatsResponse) {
185232
// _nodes/stats/discovery must never fail due to any exception
186233
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;
@@ -29,11 +43,13 @@
2943
import java.nio.file.Files;
3044
import java.nio.file.Path;
3145
import java.util.Arrays;
46+
import java.util.Collections;
3247
import java.util.List;
3348
import java.util.Locale;
3449
import java.util.Map;
3550
import java.util.Objects;
3651
import java.util.concurrent.ExecutionException;
52+
import java.util.stream.Collectors;
3753

3854
import static org.opensearch.cluster.coordination.ClusterBootstrapService.INITIAL_CLUSTER_MANAGER_NODES_SETTING;
3955
import static org.opensearch.cluster.metadata.IndexMetadata.INDEX_READ_ONLY_SETTING;
@@ -46,6 +62,11 @@
4662

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

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

91151
// Step - 2 Replace all nodes in the cluster with new nodes. This ensures new cluster state doesn't have previous index metadata
92152
resetCluster(dataNodeCount, clusterManagerNodeCount);
@@ -104,7 +164,24 @@ public void testFullClusterRestore() throws Exception {
104164
);
105165
validateMetadata(List.of(INDEX_NAME));
106166
verifyRedIndicesAndTriggerRestore(indexStats, INDEX_NAME, true);
107-
167+
clusterService().state()
168+
.metadata()
169+
.coordinationMetadata()
170+
.getVotingConfigExclusions()
171+
.stream()
172+
.forEach(config -> assertTrue(Arrays.stream(EXCLUDED_NODES).anyMatch(node -> node.equals(config.getNodeId()))));
173+
assertFalse(clusterService().state().metadata().templates().isEmpty());
174+
assertTrue(clusterService().state().metadata().templates().containsKey(TEMPLATE_NAME));
175+
assertFalse(clusterService().state().metadata().settings().isEmpty());
176+
assertFalse(clusterService().state().metadata().settings().getAsBoolean(SETTING_READ_ONLY_SETTING.getKey(), true));
177+
assertNotNull(clusterService().state().metadata().custom("component_template"));
178+
ComponentTemplateMetadata componentTemplateMetadata = clusterService().state().metadata().custom("component_template");
179+
assertFalse(componentTemplateMetadata.componentTemplates().isEmpty());
180+
assertTrue(componentTemplateMetadata.componentTemplates().containsKey(COMPONENT_TEMPLATE_NAME));
181+
assertNotNull(clusterService().state().metadata().custom("index_template"));
182+
ComposableIndexTemplateMetadata composableIndexTemplate = clusterService().state().metadata().custom("index_template");
183+
assertFalse(composableIndexTemplate.indexTemplates().isEmpty());
184+
assertTrue(composableIndexTemplate.indexTemplates().containsKey(COMPOSABLE_TEMPLATE_NAME));
108185
}
109186

110187
/**

0 commit comments

Comments
 (0)