|
19 | 19 |
|
20 | 20 | package org.elasticsearch.repositories;
|
21 | 21 |
|
| 22 | +import org.elasticsearch.ElasticsearchParseException; |
22 | 23 | import org.elasticsearch.common.UUIDs;
|
23 | 24 | import org.elasticsearch.common.bytes.BytesReference;
|
24 | 25 | import org.elasticsearch.common.xcontent.ToXContent;
|
| 26 | +import org.elasticsearch.common.xcontent.XContent; |
25 | 27 | import org.elasticsearch.common.xcontent.XContentBuilder;
|
26 | 28 | import org.elasticsearch.common.xcontent.XContentParser;
|
| 29 | +import org.elasticsearch.common.xcontent.XContentType; |
27 | 30 | import org.elasticsearch.common.xcontent.json.JsonXContent;
|
28 | 31 | import org.elasticsearch.snapshots.SnapshotId;
|
29 | 32 | import org.elasticsearch.snapshots.SnapshotState;
|
|
39 | 42 | import java.util.Map;
|
40 | 43 | import java.util.Set;
|
41 | 44 |
|
| 45 | +import static java.util.Collections.emptySet; |
| 46 | +import static java.util.Collections.singleton; |
42 | 47 | import static org.elasticsearch.repositories.RepositoryData.EMPTY_REPO_GEN;
|
| 48 | +import static org.hamcrest.Matchers.empty; |
| 49 | +import static org.hamcrest.Matchers.equalTo; |
43 | 50 | import static org.hamcrest.Matchers.greaterThan;
|
44 | 51 |
|
45 | 52 | /**
|
@@ -101,15 +108,18 @@ public void testAddSnapshots() {
|
101 | 108 | public void testInitIndices() {
|
102 | 109 | final int numSnapshots = randomIntBetween(1, 30);
|
103 | 110 | final Map<String, SnapshotId> snapshotIds = new HashMap<>(numSnapshots);
|
| 111 | + final Map<String, SnapshotState> snapshotStates = new HashMap<>(numSnapshots); |
104 | 112 | for (int i = 0; i < numSnapshots; i++) {
|
105 | 113 | final SnapshotId snapshotId = new SnapshotId(randomAlphaOfLength(8), UUIDs.randomBase64UUID());
|
106 | 114 | snapshotIds.put(snapshotId.getUUID(), snapshotId);
|
| 115 | + snapshotStates.put(snapshotId.getUUID(), randomFrom(SnapshotState.values())); |
107 | 116 | }
|
108 | 117 | RepositoryData repositoryData = new RepositoryData(EMPTY_REPO_GEN, snapshotIds,
|
109 | 118 | Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList());
|
110 | 119 | // test that initializing indices works
|
111 | 120 | Map<IndexId, Set<SnapshotId>> indices = randomIndices(snapshotIds);
|
112 |
| - RepositoryData newRepoData = repositoryData.initIndices(indices); |
| 121 | + RepositoryData newRepoData = new RepositoryData(repositoryData.getGenId(), snapshotIds, snapshotStates, indices, |
| 122 | + new ArrayList<>(repositoryData.getIncompatibleSnapshotIds())); |
113 | 123 | List<SnapshotId> expected = new ArrayList<>(repositoryData.getSnapshotIds());
|
114 | 124 | Collections.sort(expected);
|
115 | 125 | List<SnapshotId> actual = new ArrayList<>(newRepoData.getSnapshotIds());
|
@@ -153,6 +163,81 @@ public void testGetSnapshotState() {
|
153 | 163 | assertNull(repositoryData.getSnapshotState(new SnapshotId(randomAlphaOfLength(8), UUIDs.randomBase64UUID())));
|
154 | 164 | }
|
155 | 165 |
|
| 166 | + public void testIndexThatReferencesAnUnknownSnapshot() throws IOException { |
| 167 | + final XContent xContent = randomFrom(XContentType.values()).xContent(); |
| 168 | + final RepositoryData repositoryData = generateRandomRepoData(); |
| 169 | + |
| 170 | + XContentBuilder builder = XContentBuilder.builder(xContent); |
| 171 | + repositoryData.snapshotsToXContent(builder, ToXContent.EMPTY_PARAMS); |
| 172 | + RepositoryData parsedRepositoryData = RepositoryData.snapshotsFromXContent(createParser(builder), repositoryData.getGenId()); |
| 173 | + assertEquals(repositoryData, parsedRepositoryData); |
| 174 | + |
| 175 | + Map<String, SnapshotId> snapshotIds = new HashMap<>(); |
| 176 | + Map<String, SnapshotState> snapshotStates = new HashMap<>(); |
| 177 | + for (SnapshotId snapshotId : parsedRepositoryData.getSnapshotIds()) { |
| 178 | + snapshotIds.put(snapshotId.getUUID(), snapshotId); |
| 179 | + snapshotStates.put(snapshotId.getUUID(), parsedRepositoryData.getSnapshotState(snapshotId)); |
| 180 | + } |
| 181 | + |
| 182 | + final IndexId corruptedIndexId = randomFrom(parsedRepositoryData.getIndices().values()); |
| 183 | + |
| 184 | + Map<IndexId, Set<SnapshotId>> indexSnapshots = new HashMap<>(); |
| 185 | + for (Map.Entry<String, IndexId> snapshottedIndex : parsedRepositoryData.getIndices().entrySet()) { |
| 186 | + IndexId indexId = snapshottedIndex.getValue(); |
| 187 | + Set<SnapshotId> snapshotsIds = new LinkedHashSet<>(parsedRepositoryData.getSnapshots(indexId)); |
| 188 | + if (corruptedIndexId.equals(indexId)) { |
| 189 | + snapshotsIds.add(new SnapshotId("_uuid", "_does_not_exist")); |
| 190 | + } |
| 191 | + indexSnapshots.put(indexId, snapshotsIds); |
| 192 | + } |
| 193 | + assertNotNull(corruptedIndexId); |
| 194 | + |
| 195 | + RepositoryData corruptedRepositoryData = new RepositoryData(parsedRepositoryData.getGenId(), snapshotIds, snapshotStates, |
| 196 | + indexSnapshots, new ArrayList<>(parsedRepositoryData.getIncompatibleSnapshotIds())); |
| 197 | + |
| 198 | + final XContentBuilder corruptedBuilder = XContentBuilder.builder(xContent); |
| 199 | + corruptedRepositoryData.snapshotsToXContent(corruptedBuilder, ToXContent.EMPTY_PARAMS); |
| 200 | + |
| 201 | + ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class, () -> |
| 202 | + RepositoryData.snapshotsFromXContent(createParser(corruptedBuilder), corruptedRepositoryData.getGenId())); |
| 203 | + assertThat(e.getMessage(), equalTo("Detected a corrupted repository, index " + corruptedIndexId + " references an unknown " + |
| 204 | + "snapshot uuid [_does_not_exist]")); |
| 205 | + } |
| 206 | + |
| 207 | + public void testIndexThatReferenceANullSnapshot() throws IOException { |
| 208 | + final XContentBuilder builder = XContentBuilder.builder(randomFrom(XContentType.JSON).xContent()); |
| 209 | + builder.startObject(); |
| 210 | + { |
| 211 | + builder.startArray("snapshots"); |
| 212 | + builder.value(new SnapshotId("_name", "_uuid")); |
| 213 | + builder.endArray(); |
| 214 | + |
| 215 | + builder.startObject("indices"); |
| 216 | + { |
| 217 | + builder.startObject("docs"); |
| 218 | + { |
| 219 | + builder.field("id", "_id"); |
| 220 | + builder.startArray("snapshots"); |
| 221 | + { |
| 222 | + builder.startObject(); |
| 223 | + if (randomBoolean()) { |
| 224 | + builder.field("name", "_name"); |
| 225 | + } |
| 226 | + builder.endObject(); |
| 227 | + } |
| 228 | + builder.endArray(); |
| 229 | + } |
| 230 | + builder.endObject(); |
| 231 | + } |
| 232 | + builder.endObject(); |
| 233 | + } |
| 234 | + builder.endObject(); |
| 235 | + |
| 236 | + ElasticsearchParseException e = expectThrows(ElasticsearchParseException.class, () -> |
| 237 | + RepositoryData.snapshotsFromXContent(createParser(builder), randomNonNegativeLong())); |
| 238 | + assertThat(e.getMessage(), equalTo("Detected a corrupted repository, index [docs/_id] references an unknown snapshot uuid [null]")); |
| 239 | + } |
| 240 | + |
156 | 241 | public static RepositoryData generateRandomRepoData() {
|
157 | 242 | final int numIndices = randomIntBetween(1, 30);
|
158 | 243 | final List<IndexId> indices = new ArrayList<>(numIndices);
|
|
0 commit comments