Reject external versioning and explicit version numbers on create (#21998)

Fixes an issue where indexing requests with operation type "create" auto-convert external versioning to internal versioning and silently ignore the version number instead of failing with an error message.
This commit is contained in:
Yannick Welsch 2016-12-09 14:21:22 +01:00 committed by GitHub
parent beb794cb0f
commit db0660a7ea
3 changed files with 82 additions and 11 deletions

View File

@ -140,9 +140,15 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
validationException = addValidationError("source is missing", validationException);
}
final long resolvedVersion = resolveVersionDefaults();
if (opType() == OpType.CREATE) {
if (versionType != VersionType.INTERNAL || version != Versions.MATCH_DELETED) {
validationException = addValidationError("create operations do not support versioning. use index instead", validationException);
if (versionType != VersionType.INTERNAL) {
validationException = addValidationError("create operations only support internal versioning. use index instead", validationException);
return validationException;
}
if (resolvedVersion != Versions.MATCH_DELETED) {
validationException = addValidationError("create operations do not support explicit versions. use index instead", validationException);
return validationException;
}
}
@ -151,8 +157,8 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
addValidationError("an id is required for a " + opType() + " operation", validationException);
}
if (!versionType.validateVersionForWrites(version)) {
validationException = addValidationError("illegal version value [" + version + "] for version type [" + versionType.name() + "]", validationException);
if (!versionType.validateVersionForWrites(resolvedVersion)) {
validationException = addValidationError("illegal version value [" + resolvedVersion + "] for version type [" + versionType.name() + "]", validationException);
}
if (versionType == VersionType.FORCE) {
@ -164,7 +170,7 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
id.getBytes(StandardCharsets.UTF_8).length, validationException);
}
if (id == null && (versionType == VersionType.INTERNAL && version == Versions.MATCH_ANY) == false) {
if (id == null && (versionType == VersionType.INTERNAL && resolvedVersion == Versions.MATCH_ANY) == false) {
validationException = addValidationError("an id must be provided if version type or value are set", validationException);
}
@ -387,10 +393,6 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
throw new IllegalArgumentException("opType must be 'create' or 'index', found: [" + opType + "]");
}
this.opType = opType;
if (opType == OpType.CREATE) {
version(Versions.MATCH_DELETED);
versionType(VersionType.INTERNAL);
}
return this;
}
@ -433,9 +435,24 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
return this;
}
/**
* Returns stored version. If currently stored version is {@link Versions#MATCH_ANY} and
* opType is {@link OpType#CREATE}, returns {@link Versions#MATCH_DELETED}.
*/
@Override
public long version() {
return this.version;
return resolveVersionDefaults();
}
/**
* Resolves the version based on operation type {@link #opType()}.
*/
private long resolveVersionDefaults() {
if (opType == OpType.CREATE && version == Versions.MATCH_ANY) {
return Versions.MATCH_DELETED;
} else {
return version;
}
}
@Override
@ -512,7 +529,12 @@ public class IndexRequest extends ReplicatedWriteRequest<IndexRequest> implement
}
out.writeBytesReference(source);
out.writeByte(opType.getId());
out.writeLong(version);
// ES versions below 5.1.2 don't know about resolveVersionDefaults but resolve the version eagerly (which messes with validation).
if (out.getVersion().before(Version.V_5_1_2_UNRELEASED)) {
out.writeLong(resolveVersionDefaults());
} else {
out.writeLong(version);
}
out.writeByte(versionType.getValue());
out.writeOptionalString(pipeline);
out.writeBoolean(isRetry);

View File

@ -18,3 +18,18 @@
id: 1
body: { foo: bar }
---
"Internal versioning with explicit version":
- do:
create:
index: test
type: test
id: 3
body: { foo: bar }
version: 5
ignore: 400
- match: { status: 400 }
- match: { error.type: action_request_validation_exception }
- match: { error.reason: "Validation Failed: 1: create operations do not support explicit versions. use index instead;" }

View File

@ -0,0 +1,34 @@
---
"External version":
- skip:
version: " - 5.1.1"
reason: validation logic only fixed from 5.1.2 onwards
- do:
create:
index: test
type: test
id: 1
body: { foo: bar }
version_type: external
version: 0
ignore: 400
- match: { status: 400 }
- match: { error.type: action_request_validation_exception }
- match: { error.reason: "Validation Failed: 1: create operations only support internal versioning. use index instead;" }
- do:
create:
index: test
type: test
id: 2
body: { foo: bar }
version_type: external
version: 5
ignore: 400
- match: { status: 400 }
- match: { error.type: action_request_validation_exception }
- match: { error.reason: "Validation Failed: 1: create operations only support internal versioning. use index instead;" }