Implement Exclude Patterns for Snapshot- and Repository Names in Get Snapshots API#77308
Implement Exclude Patterns for Snapshot- and Repository Names in Get Snapshots API#77308original-brownbear merged 21 commits intoelastic:masterfrom original-brownbear:support-negative-snapshot-patterns
Conversation
…Snapshots API It's in the title. Adds support for exclude patterns combined with wildcard requests similar to what we support for index names.
|
Pinging @elastic/es-distributed (Team:Distributed) |
tlrx
left a comment
There was a problem hiding this comment.
LGTM - I left minor comments, feel free to address
server/src/internalClusterTest/java/org/elasticsearch/snapshots/GetSnapshotsIT.java
Outdated
Show resolved
Hide resolved
| "-" + otherPrefixSnapshot1, | ||
| "-" + otherPrefixSnapshot2 | ||
| ); | ||
| assertThat(allInOtherWithoutOtherExplicit, is(allInOther)); |
There was a problem hiding this comment.
Should we test the result when a snapshot is both included and excluded?
There was a problem hiding this comment.
++ added explicit check for this case
| final Set<String> repositoriesNotToGet = new HashSet<>(); | ||
| for (String repositoryOrPattern : repoNames) { | ||
| if (Regex.isSimpleMatchPattern(repositoryOrPattern) == false) { | ||
| if (seenWildcard && repositoryOrPattern.length() > 1 && repositoryOrPattern.startsWith("-")) { |
There was a problem hiding this comment.
I suppose we could iterate 2 times over the repositories, the first time to match repositories against include patterns ad the second to filter out matching repos with exclude patterns? Anyway the current code works too.
There was a problem hiding this comment.
Can we perhaps do this similar to the slm-change, where we first derive the include/exclude patterns and then run through the repos? And then extract the logic to a shared method to use such that we are sure that the include/exclude logic works the same.
There was a problem hiding this comment.
I dried up and shortened the logic quite a bit now across repos and snapshots but I couldn't use the exact same code because of the special case handling for stuff like _current and 404 behavior. Still should be more efficient and easier to read now I hope.
| final List<String> namesRepo2 = createNSnapshots(repoName2, randomIntBetween(1, 5)); | ||
| final List<String> namesOtherRepo = createNSnapshots(otherRepo, randomIntBetween(1, 5)); | ||
|
|
||
| final Collection<String> allSnapshotNames = new HashSet<>(namesRepo1); |
There was a problem hiding this comment.
Consider concatenating repos with the Streams API:
Stream.concat(namesRepo1.stream(), namesRepo2.stream()).collect(Collectors.toSet())
.../org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java
Outdated
Show resolved
Hide resolved
.../org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java
Outdated
Show resolved
Hide resolved
henningandersen
left a comment
There was a problem hiding this comment.
Left a few comments to consider.
| final Set<String> repositoriesNotToGet = new HashSet<>(); | ||
| for (String repositoryOrPattern : repoNames) { | ||
| if (Regex.isSimpleMatchPattern(repositoryOrPattern) == false) { | ||
| if (seenWildcard && repositoryOrPattern.length() > 1 && repositoryOrPattern.startsWith("-")) { |
There was a problem hiding this comment.
Can we perhaps do this similar to the slm-change, where we first derive the include/exclude patterns and then run through the repos? And then extract the logic to a shared method to use such that we are sure that the include/exclude logic works the same.
| } else { | ||
| for (String snapshotOrPattern : snapshots) { | ||
| if (GetSnapshotsRequest.CURRENT_SNAPSHOT.equalsIgnoreCase(snapshotOrPattern)) { | ||
| if (seenWildcard && snapshotOrPattern.length() > 1 && snapshotOrPattern.startsWith("-")) { |
There was a problem hiding this comment.
similarly to the repo-name matching, can we derive the include/exclude pattern lists first and share most of the logic between the two (and slm-policy)?
There was a problem hiding this comment.
++ makes sense, the logic isn't exactly the same because of the concrete snapshot name -> not found -> throw case but I'll dry it up. I'll wait for the other PR to land to continue here then :)
There was a problem hiding this comment.
On second thought, no we can't use the same logic as there's a difference between how the resolution works for policies and repositories/snapshots. For repositories and snapshots, if we have a concrete/non-wildcard pattern in the mix, we throw a 404ish exception if we can't find the request repo/snapshot. We don't do any such thing for SLM policies which never cause exceptions to be thrown (which makes sense IMO). I'll try to simplify the logic a little regardless :)
There was a problem hiding this comment.
I would think we could extract the include/exclude patterns in one method shared between multiple purposes? And then run through them afterwards handling the exceptions etc.
There was a problem hiding this comment.
The thing is, we have different behavior between the repos API (where we loop over the patterns and then nest the repos under them) while we can do the more efficient way of going over all the snapshot names and then matching against all patterns in one go (because we order the repos according to the order of the patterns instead of by their name or so).
It doesn't really seem like there's a simple way of drying this up but then again note that we're going to move the snapshot name logic away from running on heap like this in a follow-up, so I'm not sure there's too much point in abstracting things away only for that abstraction to become redundant in a week?
server/src/internalClusterTest/java/org/elasticsearch/snapshots/GetSnapshotsIT.java
Outdated
Show resolved
Hide resolved
| patternOtherRepo, | ||
| GetSnapshotsRequest.SortBy.REPOSITORY, | ||
| order, | ||
| "-" + otherPrefixSnapshot1, |
There was a problem hiding this comment.
nit: it seems odd that for the repo pattern we pass in a comma-separated string, whereas for the names we pass in a list of name patterns. I would prefer to see this harmonized.
There was a problem hiding this comment.
harmonized to using arrays/var-arg for both :)
| ); | ||
| } | ||
|
|
||
| public void testExcludePatterns() throws Exception { |
There was a problem hiding this comment.
Can we add a test validating that using -xyz finds such a snapshot (and repo) if no wildcard is specified first, i.e., at that we can still find snapshots/repos starting with -?
There was a problem hiding this comment.
Good point! -> added a couple of tests around this scenario now.
|
Thanks Henning, all points addressed now (though I couldn't dry things up as requested I'm afraid). |
|
Jenkins run elasticsearch-ci/packaging-tests-windows-sample |
1 similar comment
|
Jenkins run elasticsearch-ci/packaging-tests-windows-sample |
|
@elasticmachine update branch |
henningandersen
left a comment
There was a problem hiding this comment.
A few smaller comments. Still hoping for a bit of code/sharing on include/exclude patterns 🙂
| `<snapshot>`:: | ||
| (Required, string) | ||
| Comma-separated list of snapshot names to retrieve. Also accepts wildcards (`*`). | ||
| Comma-separated list of snapshot names to retrieve. Also accepts wildcards (`*`) as well as combining wildcards and exclude patterns |
There was a problem hiding this comment.
Can we align the text between repo and name match? Otherwise I end up searching for the difference between the text to understand if there is some difference...
Perhaps just state
Wildcard (`*`) expressions are supported including combining wildcards with exclude patterns starting with `-`
like above?
There was a problem hiding this comment.
Right, that was pointless, made it the same for both as suggested now.
| } else { | ||
| for (String snapshotOrPattern : snapshots) { | ||
| if (GetSnapshotsRequest.CURRENT_SNAPSHOT.equalsIgnoreCase(snapshotOrPattern)) { | ||
| if (seenWildcard && snapshotOrPattern.length() > 1 && snapshotOrPattern.startsWith("-")) { |
There was a problem hiding this comment.
I would think we could extract the include/exclude patterns in one method shared between multiple purposes? And then run through them afterwards handling the exceptions etc.
| if (Regex.isSimpleMatchPattern(repositoryOrPattern) == false) { | ||
| repositoriesToGet.add(repositoryOrPattern); | ||
| } | ||
| final List<String> includePatterns = new ArrayList<>(); |
There was a problem hiding this comment.
I think the new exclude functionality also affects the list repositories API, we should also update the documentation for that API then.
There was a problem hiding this comment.
++ udpated
| ) | ||
| ) | ||
| ); | ||
| } |
There was a problem hiding this comment.
Can we also verify that non-existing*,-weird-snapshot-1 does not return -weird-snapshot-1? And that *,--weird-snapshot-1 also does not return it? And that -* returns all - prefixed snapshots.
There was a problem hiding this comment.
++ added those cases :)
…ns' into support-negative-snapshot-patterns
|
Thanks @henningandersen! addresed all points but sharing the pattern resolution code, to me at least it seems with the way we do the ordering and not-ordering when resolving things, it's going to be pain to share code at this point in time I think, but lets see what you think :) |
|
Alright @henningandersen this should be good for another round. Implemented |
|
|
||
| `<snapshot>`:: | ||
| (Required, string) | ||
| Comma-separated list of snapshot names to retrieve. Also accepts wildcards (`*`). |
There was a problem hiding this comment.
I think we still want to include this bit "Comma-separated list of snapshot names to retrieve. "?
|
Thanks everyone! |
It's in the title. Adds support for exclude patterns combined with wildcard requests
similar to what we support for index names.