3333package org .opensearch .repositories .blobstore ;
3434
3535import org .opensearch .action .admin .cluster .repositories .get .GetRepositoriesResponse ;
36+ import org .opensearch .action .admin .cluster .repositories .verify .VerifyRepositoryResponse ;
37+ import org .opensearch .action .support .master .AcknowledgedResponse ;
3638import org .opensearch .client .Client ;
3739import org .opensearch .cluster .metadata .RepositoryMetadata ;
3840import org .opensearch .common .settings .Settings ;
4143import org .opensearch .gateway .remote .RemoteClusterStateService ;
4244import org .opensearch .index .IndexSettings ;
4345import org .opensearch .index .snapshots .blobstore .RemoteStoreShardShallowCopySnapshot ;
46+ import org .opensearch .indices .RemoteStoreSettings ;
4447import org .opensearch .indices .replication .common .ReplicationType ;
4548import org .opensearch .repositories .IndexId ;
4649import org .opensearch .repositories .RepositoriesService ;
4750import org .opensearch .repositories .RepositoryData ;
51+ import org .opensearch .repositories .RepositoryException ;
4852import org .opensearch .repositories .fs .FsRepository ;
4953import org .opensearch .snapshots .SnapshotId ;
5054import org .opensearch .snapshots .SnapshotInfo ;
55+ import org .opensearch .snapshots .SnapshotsService ;
5156import org .opensearch .test .OpenSearchIntegTestCase ;
5257
5358import java .io .IOException ;
6469import static org .opensearch .node .remotestore .RemoteStoreNodeAttribute .REMOTE_STORE_REPOSITORY_TYPE_ATTRIBUTE_KEY_FORMAT ;
6570import static org .opensearch .node .remotestore .RemoteStoreNodeAttribute .REMOTE_STORE_SEGMENT_REPOSITORY_NAME_ATTRIBUTE_KEY ;
6671import static org .opensearch .node .remotestore .RemoteStoreNodeAttribute .REMOTE_STORE_TRANSLOG_REPOSITORY_NAME_ATTRIBUTE_KEY ;
72+ import static org .opensearch .repositories .blobstore .BlobStoreRepository .REMOTE_STORE_INDEX_SHALLOW_COPY ;
73+ import static org .opensearch .repositories .blobstore .BlobStoreRepository .SHALLOW_SNAPSHOT_V2 ;
74+ import static org .opensearch .test .hamcrest .OpenSearchAssertions .assertAcked ;
6775import static org .hamcrest .Matchers .equalTo ;
6876
6977/**
@@ -81,6 +89,7 @@ protected Settings nodeSettings() {
8189 .put (Environment .PATH_HOME_SETTING .getKey (), tempDir )
8290 .put (Environment .PATH_REPO_SETTING .getKey (), tempDir .resolve ("repo" ))
8391 .put (Environment .PATH_SHARED_DATA_SETTING .getKey (), tempDir .getParent ())
92+ .put (RemoteStoreSettings .CLUSTER_REMOTE_STORE_PINNED_TIMESTAMP_ENABLED .getKey (), true )
8493 .build ();
8594 }
8695
@@ -373,4 +382,119 @@ public void testRetrieveShallowCopySnapshotCase2() throws IOException {
373382 assertThat (snapshotIds , equalTo (originalSnapshots ));
374383 }
375384
385+ public void testRepositoryCreationShallowV2 () throws Exception {
386+ Client client = client ();
387+
388+ Settings snapshotRepoSettings1 = Settings .builder ()
389+ .put (node ().settings ())
390+ .put ("location" , OpenSearchIntegTestCase .randomRepoPath (node ().settings ()))
391+ .put (REMOTE_STORE_INDEX_SHALLOW_COPY .getKey (), true )
392+ .put (SHALLOW_SNAPSHOT_V2 .getKey (), true )
393+ .build ();
394+
395+ String invalidRepoName = "test" + SnapshotsService .SNAPSHOT_PINNED_TIMESTAMP_DELIMITER + "repo-1" ;
396+ try {
397+ createRepository (client , invalidRepoName , snapshotRepoSettings1 );
398+ } catch (RepositoryException e ) {
399+ assertEquals (
400+ "["
401+ + invalidRepoName
402+ + "] setting shallow_snapshot_v2 cannot be enabled for repository with __ in the name as this delimiter is used to create pinning entity" ,
403+ e .getMessage ()
404+ );
405+ }
406+
407+ // Create repo with shallow snapshot V2 enabled
408+ createRepository (client , "test-repo-1" , snapshotRepoSettings1 );
409+
410+ logger .info ("--> verify the repository" );
411+ VerifyRepositoryResponse verifyRepositoryResponse = client .admin ().cluster ().prepareVerifyRepository ("test-repo-1" ).get ();
412+ assertNotNull (verifyRepositoryResponse .getNodes ());
413+
414+ GetRepositoriesResponse getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-1" ).get ();
415+ assertTrue (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
416+
417+ Settings snapshotRepoSettings2 = Settings .builder ()
418+ .put (node ().settings ())
419+ .put ("location" , OpenSearchIntegTestCase .randomRepoPath (node ().settings ()))
420+ .put (REMOTE_STORE_INDEX_SHALLOW_COPY .getKey (), true )
421+ .put (SHALLOW_SNAPSHOT_V2 .getKey (), true )
422+ .build ();
423+
424+ // Create another repo with shallow snapshot V2 enabled, this should fail.
425+ try {
426+ createRepository (client , "test-repo-2" , snapshotRepoSettings2 );
427+ } catch (RepositoryException e ) {
428+ assertEquals (
429+ "[test-repo-2] setting shallow_snapshot_v2 cannot be enabled as this setting can be enabled only on one repository and one or more repositories in the cluster have the setting as enabled" ,
430+ e .getMessage ()
431+ );
432+ }
433+
434+ // Disable shallow snapshot V2 setting on test-repo-1
435+ updateRepository (
436+ client ,
437+ "test-repo-1" ,
438+ Settings .builder ().put (snapshotRepoSettings1 ).put (SHALLOW_SNAPSHOT_V2 .getKey (), false ).build ()
439+ );
440+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-1" ).get ();
441+ assertFalse (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
442+
443+ // Create test-repo-2 with shallow snapshot V2 enabled, this should pass now.
444+ createRepository (client , "test-repo-2" , snapshotRepoSettings2 );
445+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-2" ).get ();
446+ assertTrue (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
447+
448+ final String indexName = "test-idx" ;
449+ createIndex (indexName );
450+ ensureGreen ();
451+ indexDocuments (client , indexName );
452+
453+ // Create pinned timestamp snapshot in test-repo-2
454+ SnapshotInfo snapshotInfo = createSnapshot ("test-repo-2" , "test-snap-2" , new ArrayList <>());
455+ assertNotNull (snapshotInfo .snapshotId ());
456+
457+ // As snapshot is present, even after disabling shallow snapshot setting in test-repo-2, we will not be able to
458+ // enable shallow snapshot v2 setting in test-repo-1
459+ updateRepository (
460+ client ,
461+ "test-repo-2" ,
462+ Settings .builder ().put (snapshotRepoSettings2 ).put (SHALLOW_SNAPSHOT_V2 .getKey (), false ).build ()
463+ );
464+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-2" ).get ();
465+ assertFalse (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
466+
467+ try {
468+ updateRepository (client , "test-repo-1" , snapshotRepoSettings1 );
469+ } catch (RepositoryException e ) {
470+ assertEquals (
471+ "[test-repo-1] setting shallow_snapshot_v2 cannot be enabled if there are existing snapshots created with shallow V2 setting using different repository." ,
472+ e .getMessage ()
473+ );
474+ }
475+
476+ // After deleting the snapshot, we will be able to enable shallow snapshot v2 setting in test-repo-1
477+ AcknowledgedResponse deleteSnapshotResponse = client ().admin ().cluster ().prepareDeleteSnapshot ("test-repo-2" , "test-snap-2" ).get ();
478+
479+ assertAcked (deleteSnapshotResponse );
480+
481+ updateRepository (client , "test-repo-1" , snapshotRepoSettings1 );
482+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-1" ).get ();
483+ assertTrue (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
484+
485+ // Having a snapshot in the same repo should allow disabling and re-enabling shallow snapshot v2 setting
486+ snapshotInfo = createSnapshot ("test-repo-1" , "test-snap-1" , new ArrayList <>());
487+ assertNotNull (snapshotInfo .snapshotId ());
488+ updateRepository (
489+ client ,
490+ "test-repo-1" ,
491+ Settings .builder ().put (snapshotRepoSettings1 ).put (SHALLOW_SNAPSHOT_V2 .getKey (), false ).build ()
492+ );
493+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-1" ).get ();
494+ assertFalse (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
495+
496+ updateRepository (client , "test-repo-1" , snapshotRepoSettings1 );
497+ getRepositoriesResponse = client .admin ().cluster ().prepareGetRepositories ("test-repo-1" ).get ();
498+ assertTrue (SHALLOW_SNAPSHOT_V2 .get (getRepositoriesResponse .repositories ().get (0 ).settings ()));
499+ }
376500}
0 commit comments