Skip to content

Commit de815de

Browse files
prwhelandavidkyleelasticmachine
authored
[Transform] Create upgrade mode (#117858) (#119352)
Prevent writes to the Transform system index while it is being reindexed during upgrade. - Add a new REST API, `_transform/set_upgrade_mode`, similar to `_ml`, which will enable via `?enabled` or disable (when omitted). - Add a new Transport action, enabling or disabling upgrade mode. When enabled, all Transforms will abort and move into the `waiting` state, preventing Transforms from running and writing to the system index. - Hook into the System Index upgrade action, calling the new Transform action to set and unset upgrade mode. Co-authored-by: David Kyle <[email protected]> Co-authored-by: Elastic Machine <[email protected]>
1 parent 02483fa commit de815de

File tree

31 files changed

+1053
-29
lines changed

31 files changed

+1053
-29
lines changed

docs/changelog/117858.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 117858
2+
summary: Create upgrade mode
3+
area: Transform
4+
type: enhancement
5+
issues: []

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ static TransportVersion def(int id) {
151151
public static final TransportVersion ERROR_TRACE_IN_TRANSPORT_HEADER = def(8_811_00_0);
152152
public static final TransportVersion FAILURE_STORE_ENABLED_BY_CLUSTER_SETTING = def(8_812_00_0);
153153
public static final TransportVersion SIMULATE_IGNORED_FIELDS = def(8_813_00_0);
154+
public static final TransportVersion TRANSFORMS_UPGRADE_MODE = def(8_814_00_0);
154155

155156
/*
156157
* STOP! READ THIS FIRST! No, really,

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/transform/TransformField.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package org.elasticsearch.xpack.core.transform;
99

10+
import org.elasticsearch.persistent.PersistentTasksCustomMetadata;
1011
import org.elasticsearch.xcontent.ParseField;
1112

1213
/*
@@ -101,5 +102,14 @@ public final class TransformField {
101102
// internal document id
102103
public static String DOCUMENT_ID_FIELD = "_id";
103104

105+
public static final PersistentTasksCustomMetadata.Assignment AWAITING_UPGRADE = new PersistentTasksCustomMetadata.Assignment(
106+
null,
107+
"Transform task will not be assigned while upgrade mode is enabled."
108+
);
109+
public static final PersistentTasksCustomMetadata.Assignment RESET_IN_PROGRESS = new PersistentTasksCustomMetadata.Assignment(
110+
null,
111+
"Transform task will not be assigned as a feature reset is in progress."
112+
);
113+
104114
private TransformField() {}
105115
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/transform/TransformMetadata.java

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
import org.elasticsearch.cluster.NamedDiff;
1515
import org.elasticsearch.cluster.metadata.Metadata;
1616
import org.elasticsearch.common.Strings;
17+
import org.elasticsearch.common.collect.Iterators;
1718
import org.elasticsearch.common.io.stream.StreamInput;
1819
import org.elasticsearch.common.io.stream.StreamOutput;
19-
import org.elasticsearch.common.xcontent.ChunkedToXContentHelper;
2020
import org.elasticsearch.core.Nullable;
2121
import org.elasticsearch.xcontent.ObjectParser;
2222
import org.elasticsearch.xcontent.ParseField;
@@ -30,8 +30,9 @@
3030
public class TransformMetadata implements Metadata.Custom {
3131
public static final String TYPE = "transform";
3232
public static final ParseField RESET_MODE = new ParseField("reset_mode");
33+
public static final ParseField UPGRADE_MODE = new ParseField("upgrade_mode");
3334

34-
public static final TransformMetadata EMPTY_METADATA = new TransformMetadata(false);
35+
public static final TransformMetadata EMPTY_METADATA = new TransformMetadata(false, false);
3536
// This parser follows the pattern that metadata is parsed leniently (to allow for enhancements)
3637
public static final ObjectParser<TransformMetadata.Builder, Void> LENIENT_PARSER = new ObjectParser<>(
3738
"" + "transform_metadata",
@@ -40,19 +41,26 @@ public class TransformMetadata implements Metadata.Custom {
4041
);
4142

4243
static {
43-
LENIENT_PARSER.declareBoolean(TransformMetadata.Builder::isResetMode, RESET_MODE);
44+
LENIENT_PARSER.declareBoolean(TransformMetadata.Builder::resetMode, RESET_MODE);
45+
LENIENT_PARSER.declareBoolean(TransformMetadata.Builder::upgradeMode, UPGRADE_MODE);
4446
}
4547

4648
private final boolean resetMode;
49+
private final boolean upgradeMode;
4750

48-
private TransformMetadata(boolean resetMode) {
51+
private TransformMetadata(boolean resetMode, boolean upgradeMode) {
4952
this.resetMode = resetMode;
53+
this.upgradeMode = upgradeMode;
5054
}
5155

52-
public boolean isResetMode() {
56+
public boolean resetMode() {
5357
return resetMode;
5458
}
5559

60+
public boolean upgradeMode() {
61+
return upgradeMode;
62+
}
63+
5664
@Override
5765
public TransportVersion getMinimalSupportedVersion() {
5866
return TransportVersions.MINIMUM_COMPATIBLE;
@@ -75,28 +83,46 @@ public Diff<Metadata.Custom> diff(Metadata.Custom previousState) {
7583

7684
public TransformMetadata(StreamInput in) throws IOException {
7785
this.resetMode = in.readBoolean();
86+
if (in.getTransportVersion().onOrAfter(TransportVersions.TRANSFORMS_UPGRADE_MODE)) {
87+
this.upgradeMode = in.readBoolean();
88+
} else {
89+
this.upgradeMode = false;
90+
}
7891
}
7992

8093
@Override
8194
public void writeTo(StreamOutput out) throws IOException {
8295
out.writeBoolean(resetMode);
96+
if (out.getTransportVersion().onOrAfter(TransportVersions.TRANSFORMS_UPGRADE_MODE)) {
97+
out.writeBoolean(upgradeMode);
98+
}
8399
}
84100

85101
@Override
86102
public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params ignored) {
87-
return ChunkedToXContentHelper.field(RESET_MODE.getPreferredName(), resetMode);
103+
return Iterators.single(
104+
((builder, params) -> builder.field(UPGRADE_MODE.getPreferredName(), upgradeMode)
105+
.field(RESET_MODE.getPreferredName(), resetMode))
106+
);
88107
}
89108

90109
public static class TransformMetadataDiff implements NamedDiff<Metadata.Custom> {
91110

92111
final boolean resetMode;
112+
final boolean upgradeMode;
93113

94114
TransformMetadataDiff(TransformMetadata before, TransformMetadata after) {
95115
this.resetMode = after.resetMode;
116+
this.upgradeMode = after.upgradeMode;
96117
}
97118

98119
public TransformMetadataDiff(StreamInput in) throws IOException {
99120
resetMode = in.readBoolean();
121+
if (in.getTransportVersion().onOrAfter(TransportVersions.TRANSFORMS_UPGRADE_MODE)) {
122+
this.upgradeMode = in.readBoolean();
123+
} else {
124+
this.upgradeMode = false;
125+
}
100126
}
101127

102128
/**
@@ -106,12 +132,15 @@ public TransformMetadataDiff(StreamInput in) throws IOException {
106132
*/
107133
@Override
108134
public Metadata.Custom apply(Metadata.Custom part) {
109-
return new TransformMetadata(resetMode);
135+
return new TransformMetadata(resetMode, upgradeMode);
110136
}
111137

112138
@Override
113139
public void writeTo(StreamOutput out) throws IOException {
114140
out.writeBoolean(resetMode);
141+
if (out.getTransportVersion().onOrAfter(TransportVersions.TRANSFORMS_UPGRADE_MODE)) {
142+
out.writeBoolean(upgradeMode);
143+
}
115144
}
116145

117146
@Override
@@ -130,7 +159,7 @@ public boolean equals(Object o) {
130159
if (this == o) return true;
131160
if (o == null || getClass() != o.getClass()) return false;
132161
TransformMetadata that = (TransformMetadata) o;
133-
return resetMode == that.resetMode;
162+
return resetMode == that.resetMode && upgradeMode == that.upgradeMode;
134163
}
135164

136165
@Override
@@ -140,12 +169,17 @@ public final String toString() {
140169

141170
@Override
142171
public int hashCode() {
143-
return Objects.hash(resetMode);
172+
return Objects.hash(resetMode, upgradeMode);
173+
}
174+
175+
public Builder builder() {
176+
return new TransformMetadata.Builder(this);
144177
}
145178

146179
public static class Builder {
147180

148181
private boolean resetMode;
182+
private boolean upgradeMode;
149183

150184
public static TransformMetadata.Builder from(@Nullable TransformMetadata previous) {
151185
return new TransformMetadata.Builder(previous);
@@ -156,16 +190,22 @@ public Builder() {}
156190
public Builder(@Nullable TransformMetadata previous) {
157191
if (previous != null) {
158192
resetMode = previous.resetMode;
193+
upgradeMode = previous.upgradeMode;
159194
}
160195
}
161196

162-
public TransformMetadata.Builder isResetMode(boolean isResetMode) {
197+
public TransformMetadata.Builder resetMode(boolean isResetMode) {
163198
this.resetMode = isResetMode;
164199
return this;
165200
}
166201

202+
public TransformMetadata.Builder upgradeMode(boolean upgradeMode) {
203+
this.upgradeMode = upgradeMode;
204+
return this;
205+
}
206+
167207
public TransformMetadata build() {
168-
return new TransformMetadata(resetMode);
208+
return new TransformMetadata(resetMode, upgradeMode);
169209
}
170210
}
171211

@@ -176,4 +216,8 @@ public static TransformMetadata getTransformMetadata(ClusterState state) {
176216
}
177217
return TransformMetadata;
178218
}
219+
220+
public static boolean upgradeMode(ClusterState state) {
221+
return getTransformMetadata(state).upgradeMode();
222+
}
179223
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.core.transform.action;
9+
10+
import org.elasticsearch.action.ActionType;
11+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
12+
13+
public class SetTransformUpgradeModeAction extends ActionType<AcknowledgedResponse> {
14+
public static final SetTransformUpgradeModeAction INSTANCE = new SetTransformUpgradeModeAction();
15+
public static final String NAME = "cluster:admin/transform/upgrade_mode";
16+
17+
private SetTransformUpgradeModeAction() {
18+
super(NAME);
19+
}
20+
}

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/authz/store/ReservedRolesStoreTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
import org.elasticsearch.xpack.core.transform.action.GetTransformStatsAction;
198198
import org.elasticsearch.xpack.core.transform.action.PreviewTransformAction;
199199
import org.elasticsearch.xpack.core.transform.action.PutTransformAction;
200+
import org.elasticsearch.xpack.core.transform.action.SetTransformUpgradeModeAction;
200201
import org.elasticsearch.xpack.core.transform.action.StartTransformAction;
201202
import org.elasticsearch.xpack.core.transform.action.StopTransformAction;
202203
import org.elasticsearch.xpack.core.transform.action.UpdateTransformAction;
@@ -3442,6 +3443,7 @@ public void testTransformAdminRole() {
34423443
assertThat(role.cluster().check(PutTransformAction.NAME, request, authentication), is(true));
34433444
assertThat(role.cluster().check(StartTransformAction.NAME, request, authentication), is(true));
34443445
assertThat(role.cluster().check(StopTransformAction.NAME, request, authentication), is(true));
3446+
assertThat(role.cluster().check(SetTransformUpgradeModeAction.NAME, request, authentication), is(true));
34453447
assertThat(role.cluster().check(DelegatePkiAuthenticationAction.NAME, request, authentication), is(false));
34463448

34473449
assertThat(role.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(false));
@@ -3531,6 +3533,7 @@ public void testTransformUserRole() {
35313533
assertThat(role.cluster().check(PutTransformAction.NAME, request, authentication), is(false));
35323534
assertThat(role.cluster().check(StartTransformAction.NAME, request, authentication), is(false));
35333535
assertThat(role.cluster().check(StopTransformAction.NAME, request, authentication), is(false));
3536+
assertThat(role.cluster().check(SetTransformUpgradeModeAction.NAME, request, authentication), is(false));
35343537
assertThat(role.cluster().check(DelegatePkiAuthenticationAction.NAME, request, authentication), is(false));
35353538
assertThat(role.cluster().check(ActivateProfileAction.NAME, request, authentication), is(false));
35363539
assertThat(role.cluster().check(SuggestProfilesAction.NAME, request, authentication), is(false));

x-pack/plugin/security/qa/operator-privileges-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/operator/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public class Constants {
115115
"cluster:admin/transform/schedule_now",
116116
"cluster:admin/transform/update",
117117
"cluster:admin/transform/upgrade",
118+
"cluster:admin/transform/upgrade_mode",
118119
"cluster:admin/transform/validate",
119120
// "cluster:admin/voting_config/add_exclusions",
120121
// "cluster:admin/voting_config/clear_exclusions",

x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformGetAndGetStatsIT.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,6 @@
3737
import static org.hamcrest.Matchers.oneOf;
3838

3939
public class TransformGetAndGetStatsIT extends TransformRestTestCase {
40-
41-
private static final String TEST_USER_NAME = "transform_user";
42-
private static final String BASIC_AUTH_VALUE_TRANSFORM_USER = basicAuthHeaderValue(TEST_USER_NAME, TEST_PASSWORD_SECURE_STRING);
43-
private static final String TEST_ADMIN_USER_NAME = "transform_admin";
44-
private static final String BASIC_AUTH_VALUE_TRANSFORM_ADMIN = basicAuthHeaderValue(TEST_ADMIN_USER_NAME, TEST_PASSWORD_SECURE_STRING);
4540
private static final String DANGLING_TASK_ERROR_MESSAGE =
4641
"Found task for transform [pivot_continuous], but no configuration for it. To delete this transform use DELETE with force=true.";
4742

x-pack/plugin/transform/qa/single-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/transform/integration/TransformRestTestCase.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,16 @@
3939
import static org.hamcrest.Matchers.is;
4040

4141
public abstract class TransformRestTestCase extends TransformCommonRestTestCase {
42-
4342
protected static final String TEST_PASSWORD = "x-pack-test-password";
4443
protected static final SecureString TEST_PASSWORD_SECURE_STRING = new SecureString(TEST_PASSWORD.toCharArray());
44+
45+
protected static final String TEST_USER_NAME = "transform_user";
46+
protected static final String BASIC_AUTH_VALUE_TRANSFORM_USER = basicAuthHeaderValue(TEST_USER_NAME, TEST_PASSWORD_SECURE_STRING);
47+
protected static final String TEST_ADMIN_USER_NAME = "transform_admin";
48+
protected static final String BASIC_AUTH_VALUE_TRANSFORM_ADMIN = basicAuthHeaderValue(
49+
TEST_ADMIN_USER_NAME,
50+
TEST_PASSWORD_SECURE_STRING
51+
);
4552
private static final String BASIC_AUTH_VALUE_SUPER_USER = basicAuthHeaderValue("x_pack_rest_user", TEST_PASSWORD_SECURE_STRING);
4653

4754
protected static final String REVIEWS_INDEX_NAME = "reviews";

0 commit comments

Comments
 (0)