1616import org .elasticsearch .common .Strings ;
1717import org .elasticsearch .common .io .stream .StreamInput ;
1818import org .elasticsearch .common .io .stream .StreamOutput ;
19+ import org .elasticsearch .core .Nullable ;
1920import org .elasticsearch .license .LicenseUtils ;
2021import org .elasticsearch .license .XPackLicenseState ;
2122import org .elasticsearch .xcontent .ConstructingObjectParser ;
3233import java .util .Objects ;
3334
3435import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY ;
36+ import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY ;
3537import static org .elasticsearch .snapshots .SearchableSnapshotsSettings .SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY ;
3638import static org .elasticsearch .xpack .core .searchablesnapshots .SearchableSnapshotsConstants .SEARCHABLE_SNAPSHOT_FEATURE ;
3739
@@ -141,10 +143,12 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
141143 IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
142144 assert indexMetadata != null : "index " + index .getName () + " must exist in the cluster state" ;
143145 String policyName = indexMetadata .getLifecyclePolicyName ();
144- if (indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME ) != null ) {
146+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
147+ if (searchableSnapshotMetadata != null ) {
148+ // TODO: allow this behavior instead of returning false, in this case the index is already a searchable a snapshot
149+ // so the most graceful way of recovery might be to use this repo
145150 // The index is already a searchable snapshot, let's see if the repository matches
146- String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
147- if (this .snapshotRepository .equals (repo ) == false ) {
151+ if (this .snapshotRepository .equals (searchableSnapshotMetadata .repositoryName ) == false ) {
148152 // Okay, different repo, we need to go ahead with the searchable snapshot
149153 logger .debug (
150154 "[{}] action is configured for index [{}] in policy [{}] which is already mounted as a searchable "
@@ -153,15 +157,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
153157 SearchableSnapshotAction .NAME ,
154158 index .getName (),
155159 policyName ,
156- repo ,
160+ searchableSnapshotMetadata . repositoryName ,
157161 this .snapshotRepository
158162 );
159163 return false ;
160164 }
161165
162166 // Check to the storage type to see if we need to convert between full <-> partial
163- final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
164- MountSearchableSnapshotRequest .Storage existingType = partial
167+ MountSearchableSnapshotRequest .Storage existingType = searchableSnapshotMetadata .partial
165168 ? MountSearchableSnapshotRequest .Storage .SHARED_CACHE
166169 : MountSearchableSnapshotRequest .Storage .FULL_COPY ;
167170 MountSearchableSnapshotRequest .Storage type = getConcreteStorageType (preActionBranchingKey );
@@ -172,7 +175,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
172175 SearchableSnapshotAction .NAME ,
173176 index .getName (),
174177 policyName ,
175- repo ,
178+ searchableSnapshotMetadata . repositoryName ,
176179 type
177180 );
178181 return true ;
@@ -215,7 +218,7 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
215218 // When generating a snapshot, we either jump to the force merge step, or we skip the
216219 // forcemerge and go straight to steps for creating the snapshot
217220 StepKey keyForSnapshotGeneration = forceMergeIndex ? forceMergeStepKey : generateSnapshotNameKey ;
218- // Branch, deciding whether there is an existing searchable snapshot snapshot that can be used for mounting the index
221+ // Branch, deciding whether there is an existing searchable snapshot that can be used for mounting the index
219222 // (in which case, skip generating a new name and the snapshot cleanup), or if we need to generate a new snapshot
220223 BranchingStep skipGeneratingSnapshotStep = new BranchingStep (
221224 skipGeneratingSnapshotKey ,
@@ -225,7 +228,8 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
225228 IndexMetadata indexMetadata = clusterState .getMetadata ().index (index );
226229 String policyName = indexMetadata .getLifecyclePolicyName ();
227230 LifecycleExecutionState lifecycleExecutionState = indexMetadata .getLifecycleExecutionState ();
228- if (lifecycleExecutionState .snapshotName () == null ) {
231+ SearchableSnapshotMetadata searchableSnapshotMetadata = extractSearchableSnapshotFromSettings (indexMetadata );
232+ if (lifecycleExecutionState .snapshotName () == null && searchableSnapshotMetadata == null ) {
229233 // No name exists, so it must be generated
230234 logger .trace (
231235 "no snapshot name for index [{}] in policy [{}] exists, so one will be generated" ,
@@ -234,8 +238,20 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
234238 );
235239 return false ;
236240 }
241+ String snapshotIndexName ;
242+ String snapshotName ;
243+ String repoName ;
244+ if (lifecycleExecutionState .snapshotName () != null ) {
245+ snapshotIndexName = lifecycleExecutionState .snapshotIndexName ();
246+ snapshotName = lifecycleExecutionState .snapshotName ();
247+ repoName = lifecycleExecutionState .snapshotRepository ();
248+ } else {
249+ snapshotIndexName = searchableSnapshotMetadata .sourceIndex ;
250+ snapshotName = searchableSnapshotMetadata .snapshotName ;
251+ repoName = searchableSnapshotMetadata .repositoryName ;
252+ }
237253
238- if (this .snapshotRepository .equals (lifecycleExecutionState . snapshotRepository () ) == false ) {
254+ if (this .snapshotRepository .equals (repoName ) == false ) {
239255 // A different repository is being used
240256 // TODO: allow this behavior instead of throwing an exception
241257 throw new IllegalArgumentException ("searchable snapshot indices may be converted only within the same repository" );
@@ -244,12 +260,14 @@ public List<Step> toSteps(Client client, String phase, StepKey nextStepKey, XPac
244260 // We can skip the generate, initial cleanup, and snapshot taking for this index, as we already have a generated snapshot.
245261 // This will jump ahead directly to the "mount snapshot" step
246262 logger .debug (
247- "an existing snapshot [{}] in repository [{}] (index name: [{}]) "
248- + "will be used for mounting [{}] as a searchable snapshot" ,
249- lifecycleExecutionState .snapshotName (),
250- lifecycleExecutionState .snapshotRepository (),
251- lifecycleExecutionState .snapshotIndexName (),
252- index .getName ()
263+ "Policy [{}] will use an existing snapshot [{}] in repository [{}] (index name: [{}]) "
264+ + "to mount [{}] as a searchable snapshot. This snapshot was found in the {}." ,
265+ policyName ,
266+ snapshotName ,
267+ snapshotRepository ,
268+ snapshotIndexName ,
269+ index .getName (),
270+ lifecycleExecutionState .snapshotName () != null ? "lifecycle execution state" : "metadata of " + index .getName ()
253271 );
254272 return true ;
255273 }
@@ -411,4 +429,18 @@ public boolean equals(Object o) {
411429 public int hashCode () {
412430 return Objects .hash (snapshotRepository , forceMergeIndex );
413431 }
432+
433+ @ Nullable
434+ static SearchableSnapshotMetadata extractSearchableSnapshotFromSettings (IndexMetadata indexMetadata ) {
435+ String indexName = indexMetadata .getSettings ().get (LifecycleSettings .SNAPSHOT_INDEX_NAME );
436+ if (indexName == null ) {
437+ return null ;
438+ }
439+ String snapshotName = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_SNAPSHOT_NAME_SETTING_KEY );
440+ String repo = indexMetadata .getSettings ().get (SEARCHABLE_SNAPSHOTS_REPOSITORY_NAME_SETTING_KEY );
441+ final boolean partial = indexMetadata .getSettings ().getAsBoolean (SEARCHABLE_SNAPSHOT_PARTIAL_SETTING_KEY , false );
442+ return new SearchableSnapshotMetadata (indexName , repo , snapshotName , partial );
443+ }
444+
445+ record SearchableSnapshotMetadata (String sourceIndex , String repositoryName , String snapshotName , boolean partial ) {};
414446}
0 commit comments