Skip to content

Commit d212b30

Browse files
author
Vladimir Dolzhenko
committed
Allow date math for naming newly-created snapshots (elastic#7939) (elastic#30479)
(cherry picked from commit fe3e025)
1 parent 7e12417 commit d212b30

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

docs/reference/modules/snapshots.asciidoc

+14
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,20 @@ By setting `include_global_state` to false it's possible to prevent the cluster
289289
the snapshot. By default, the entire snapshot will fail if one or more indices participating in the snapshot don't have
290290
all primary shards available. This behaviour can be changed by setting `partial` to `true`.
291291

292+
Snapshot names can be automatically derived using <<date-math-index-names,date math expressions>>, similarly as when creating
293+
new indices. Note that special characters need to be URI encoded.
294+
295+
For example, creating a snapshot with the current day in the name, like `snapshot-2018.05.11`, can be achieved with
296+
the following command:
297+
[source,js]
298+
-----------------------------------
299+
# PUT /_snapshot/my_backup/<snapshot-{now/d}>
300+
PUT /_snapshot/my_backup/%3Csnapshot-%7Bnow%2Fd%7D%3E
301+
-----------------------------------
302+
// CONSOLE
303+
// TEST[continued]
304+
305+
292306
The index snapshot process is incremental. In the process of making the index snapshot Elasticsearch analyses
293307
the list of the index files that are already stored in the repository and copies only files that were created or
294308
changed since the last snapshot. That allows multiple snapshots to be preserved in the repository in a compact form.

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/TransportCreateSnapshotAction.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ protected ClusterBlockException checkBlock(CreateSnapshotRequest request, Cluste
7171

7272
@Override
7373
protected void masterOperation(final CreateSnapshotRequest request, ClusterState state, final ActionListener<CreateSnapshotResponse> listener) {
74+
final String snapshotName = indexNameExpressionResolver.resolveDateMathExpression(request.snapshot());
7475
SnapshotsService.SnapshotRequest snapshotRequest =
75-
new SnapshotsService.SnapshotRequest(request.repository(), request.snapshot(), "create_snapshot [" + request.snapshot() + "]")
76+
new SnapshotsService.SnapshotRequest(request.repository(), snapshotName, "create_snapshot [" + snapshotName + "]")
7677
.indices(request.indices())
7778
.indicesOptions(request.indicesOptions())
7879
.partial(request.partial())
@@ -87,7 +88,7 @@ public void onResponse() {
8788
@Override
8889
public void onSnapshotCompletion(Snapshot snapshot, SnapshotInfo snapshotInfo) {
8990
if (snapshot.getRepository().equals(request.repository()) &&
90-
snapshot.getSnapshotId().getName().equals(request.snapshot())) {
91+
snapshot.getSnapshotId().getName().equals(snapshotName)) {
9192
listener.onResponse(new CreateSnapshotResponse(snapshotInfo));
9293
snapshotsService.removeListener(this);
9394
}
@@ -96,7 +97,7 @@ public void onSnapshotCompletion(Snapshot snapshot, SnapshotInfo snapshotInfo) {
9697
@Override
9798
public void onSnapshotFailure(Snapshot snapshot, Exception e) {
9899
if (snapshot.getRepository().equals(request.repository()) &&
99-
snapshot.getSnapshotId().getName().equals(request.snapshot())) {
100+
snapshot.getSnapshotId().getName().equals(snapshotName)) {
100101
listener.onFailure(e);
101102
snapshotsService.removeListener(this);
102103
}

server/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreIT.java

+38
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
3333
import org.elasticsearch.action.index.IndexRequestBuilder;
3434
import org.elasticsearch.action.support.ActiveShardCount;
35+
import org.elasticsearch.client.AdminClient;
3536
import org.elasticsearch.client.Client;
3637
import org.elasticsearch.client.node.NodeClient;
3738
import org.elasticsearch.cluster.ClusterState;
@@ -41,6 +42,7 @@
4142
import org.elasticsearch.cluster.SnapshotDeletionsInProgress;
4243
import org.elasticsearch.cluster.SnapshotsInProgress;
4344
import org.elasticsearch.cluster.health.ClusterHealthStatus;
45+
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
4446
import org.elasticsearch.cluster.metadata.MetaData;
4547
import org.elasticsearch.cluster.metadata.MetaDataIndexStateService;
4648
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
@@ -49,13 +51,15 @@
4951
import org.elasticsearch.common.Nullable;
5052
import org.elasticsearch.common.ParseField;
5153
import org.elasticsearch.common.Priority;
54+
import org.elasticsearch.common.Strings;
5255
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
5356
import org.elasticsearch.common.io.stream.StreamInput;
5457
import org.elasticsearch.common.io.stream.Writeable;
5558
import org.elasticsearch.common.settings.Settings;
5659
import org.elasticsearch.common.settings.SettingsFilter;
5760
import org.elasticsearch.common.unit.ByteSizeUnit;
5861
import org.elasticsearch.common.unit.TimeValue;
62+
import org.elasticsearch.common.util.set.Sets;
5963
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
6064
import org.elasticsearch.common.xcontent.XContentParser;
6165
import org.elasticsearch.discovery.zen.ElectMasterService;
@@ -68,6 +72,7 @@
6872
import org.elasticsearch.rest.RestController;
6973
import org.elasticsearch.rest.RestRequest;
7074
import org.elasticsearch.rest.RestResponse;
75+
import org.elasticsearch.rest.RestStatus;
7176
import org.elasticsearch.rest.action.admin.cluster.RestClusterStateAction;
7277
import org.elasticsearch.rest.action.admin.cluster.RestGetRepositoriesAction;
7378
import org.elasticsearch.snapshots.mockstore.MockRepository;
@@ -96,6 +101,7 @@
96101
import static org.hamcrest.Matchers.equalTo;
97102
import static org.hamcrest.Matchers.greaterThan;
98103
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
104+
import static org.hamcrest.Matchers.hasSize;
99105
import static org.hamcrest.Matchers.lessThan;
100106
import static org.hamcrest.Matchers.not;
101107
import static org.hamcrest.Matchers.notNullValue;
@@ -981,6 +987,38 @@ public void testRestoreShrinkIndex() throws Exception {
981987
ensureYellow();
982988
}
983989

990+
public void testSnapshotWithDateMath() {
991+
final String repo = "repo";
992+
final AdminClient admin = client().admin();
993+
994+
final IndexNameExpressionResolver nameExpressionResolver = new IndexNameExpressionResolver(Settings.EMPTY);
995+
final String snapshotName = "<snapshot-{now/d}>";
996+
997+
logger.info("--> creating repository");
998+
assertAcked(admin.cluster().preparePutRepository(repo).setType("fs")
999+
.setSettings(Settings.builder().put("location", randomRepoPath())
1000+
.put("compress", randomBoolean())));
1001+
1002+
final String expression1 = nameExpressionResolver.resolveDateMathExpression(snapshotName);
1003+
logger.info("--> creating date math snapshot");
1004+
CreateSnapshotResponse snapshotResponse =
1005+
admin.cluster().prepareCreateSnapshot(repo, snapshotName)
1006+
.setIncludeGlobalState(true)
1007+
.setWaitForCompletion(true)
1008+
.get();
1009+
assertThat(snapshotResponse.status(), equalTo(RestStatus.OK));
1010+
// snapshot could be taken before or after a day rollover
1011+
final String expression2 = nameExpressionResolver.resolveDateMathExpression(snapshotName);
1012+
1013+
SnapshotsStatusResponse response = admin.cluster().prepareSnapshotStatus(repo)
1014+
.setSnapshots(Sets.newHashSet(expression1, expression2).toArray(Strings.EMPTY_ARRAY))
1015+
.setIgnoreUnavailable(true)
1016+
.get();
1017+
List<SnapshotStatus> snapshots = response.getSnapshots();
1018+
assertThat(snapshots, hasSize(1));
1019+
assertThat(snapshots.get(0).getState().completed(), equalTo(true));
1020+
}
1021+
9841022
public static class SnapshottableMetadata extends TestCustomMetaData {
9851023
public static final String TYPE = "test_snapshottable";
9861024

0 commit comments

Comments
 (0)