17
17
import org .elasticsearch .common .Strings ;
18
18
import org .elasticsearch .common .settings .Settings ;
19
19
import org .elasticsearch .common .unit .ByteSizeValue ;
20
+ import org .elasticsearch .common .unit .Processors ;
20
21
import org .elasticsearch .common .xcontent .support .XContentMapValues ;
21
22
import org .elasticsearch .xcontent .json .JsonXContent ;
22
23
31
32
import static org .hamcrest .Matchers .is ;
32
33
33
34
public class DesiredNodesUpgradeIT extends AbstractRollingTestCase {
35
+ private enum ProcessorsPrecision {
36
+ DOUBLE ,
37
+ FLOAT
38
+ }
39
+
34
40
public void testUpgradeDesiredNodes () throws Exception {
35
41
// Desired nodes was introduced in 8.1
36
42
if (UPGRADE_FROM_VERSION .before (Version .V_8_1_0 )) {
37
43
return ;
38
44
}
39
45
46
+ if (UPGRADE_FROM_VERSION .onOrAfter (Processors .DOUBLE_PROCESSORS_SUPPORT_VERSION )) {
47
+ assertUpgradedNodesCanReadDesiredNodes ();
48
+ } else if (UPGRADE_FROM_VERSION .onOrAfter (DesiredNode .RANGE_FLOAT_PROCESSORS_SUPPORT_VERSION )) {
49
+ assertDesiredNodesUpdatedWithRoundedUpFloatsAreIdempotent ();
50
+ } else {
51
+ assertDesiredNodesWithFloatProcessorsAreRejectedInOlderVersions ();
52
+ }
53
+ }
54
+
55
+ private void assertUpgradedNodesCanReadDesiredNodes () throws Exception {
56
+ final int desiredNodesVersion = switch (CLUSTER_TYPE ) {
57
+ case OLD -> 1 ;
58
+ case MIXED -> FIRST_MIXED_ROUND ? 2 : 3 ;
59
+ case UPGRADED -> 4 ;
60
+ };
61
+
62
+ if (CLUSTER_TYPE != ClusterType .OLD ) {
63
+ final Map <String , Object > desiredNodes = getLatestDesiredNodes ();
64
+ final String historyId = extractValue (desiredNodes , "history_id" );
65
+ final int version = extractValue (desiredNodes , "version" );
66
+ assertThat (historyId , is (equalTo ("upgrade_test" )));
67
+ assertThat (version , is (equalTo (desiredNodesVersion - 1 )));
68
+ }
69
+
70
+ addClusterNodesToDesiredNodesWithProcessorsOrProcessorRanges (desiredNodesVersion , ProcessorsPrecision .DOUBLE );
71
+ assertAllDesiredNodesAreActualized ();
72
+ }
73
+
74
+ private void assertDesiredNodesUpdatedWithRoundedUpFloatsAreIdempotent () throws Exception {
75
+ // We define the same set of desired nodes to ensure that they are equal across all
76
+ // the test runs, otherwise we cannot guarantee an idempotent update in this test
77
+ final var desiredNodes = getNodeNames ().stream ()
78
+ .map (
79
+ nodeName -> new DesiredNode (
80
+ Settings .builder ().put (NODE_NAME_SETTING .getKey (), nodeName ).build (),
81
+ 1238.49922909 ,
82
+ ByteSizeValue .ofGb (32 ),
83
+ ByteSizeValue .ofGb (128 ),
84
+ Version .CURRENT
85
+ )
86
+ )
87
+ .toList ();
88
+
89
+ final int desiredNodesVersion = switch (CLUSTER_TYPE ) {
90
+ case OLD -> 1 ;
91
+ case MIXED -> FIRST_MIXED_ROUND ? 2 : 3 ;
92
+ case UPGRADED -> 4 ;
93
+ };
94
+
95
+ if (CLUSTER_TYPE != ClusterType .OLD ) {
96
+ updateDesiredNodes (desiredNodes , desiredNodesVersion - 1 );
97
+ }
98
+ for (int i = 0 ; i < 2 ; i ++) {
99
+ updateDesiredNodes (desiredNodes , desiredNodesVersion );
100
+ }
101
+
102
+ final Map <String , Object > latestDesiredNodes = getLatestDesiredNodes ();
103
+ final int latestDesiredNodesVersion = extractValue (latestDesiredNodes , "version" );
104
+ assertThat (latestDesiredNodesVersion , is (equalTo (desiredNodesVersion )));
105
+
106
+ if (CLUSTER_TYPE == ClusterType .UPGRADED ) {
107
+ assertAllDesiredNodesAreActualized ();
108
+ }
109
+ }
110
+
111
+ private void assertDesiredNodesWithFloatProcessorsAreRejectedInOlderVersions () throws Exception {
40
112
switch (CLUSTER_TYPE ) {
41
113
case OLD -> addClusterNodesToDesiredNodesWithIntegerProcessors (1 );
42
114
case MIXED -> {
43
115
int version = FIRST_MIXED_ROUND ? 2 : 3 ;
44
- if (UPGRADE_FROM_VERSION .onOrAfter (DesiredNode .RANGE_FLOAT_PROCESSORS_SUPPORT_VERSION )) {
45
- addClusterNodesToDesiredNodesWithFloatProcessorsOrProcessorRanges (version );
46
- } else {
47
- // Processor ranges or float processors are forbidden during upgrades: 8.2 -> 8.3 clusters
48
- final var responseException = expectThrows (
49
- ResponseException .class ,
50
- () -> addClusterNodesToDesiredNodesWithFloatProcessorsOrProcessorRanges (version )
51
- );
52
- final var statusCode = responseException .getResponse ().getStatusLine ().getStatusCode ();
53
- assertThat (statusCode , is (equalTo (400 )));
54
- }
116
+ // Processor ranges or float processors are forbidden during upgrades: 8.2 -> 8.3 clusters
117
+ final var responseException = expectThrows (
118
+ ResponseException .class ,
119
+ () -> addClusterNodesToDesiredNodesWithProcessorsOrProcessorRanges (version , ProcessorsPrecision .FLOAT )
120
+ );
121
+ final var statusCode = responseException .getResponse ().getStatusLine ().getStatusCode ();
122
+ assertThat (statusCode , is (equalTo (400 )));
55
123
}
56
124
case UPGRADED -> {
57
125
assertAllDesiredNodesAreActualized ();
58
- addClusterNodesToDesiredNodesWithFloatProcessorsOrProcessorRanges ( 4 );
126
+ addClusterNodesToDesiredNodesWithProcessorsOrProcessorRanges ( 4 , ProcessorsPrecision . FLOAT );
59
127
}
60
128
}
61
129
130
+ getLatestDesiredNodes ();
131
+ }
132
+
133
+ private Map <String , Object > getLatestDesiredNodes () throws IOException {
62
134
final var getDesiredNodesRequest = new Request ("GET" , "/_internal/desired_nodes/_latest" );
63
135
final var response = client ().performRequest (getDesiredNodesRequest );
64
136
assertThat (response .getStatusLine ().getStatusCode (), is (equalTo (200 )));
137
+ return responseAsMap (response );
65
138
}
66
139
67
140
private void assertAllDesiredNodesAreActualized () throws Exception {
@@ -77,32 +150,34 @@ private void assertAllDesiredNodesAreActualized() throws Exception {
77
150
}
78
151
}
79
152
80
- private void addClusterNodesToDesiredNodesWithFloatProcessorsOrProcessorRanges (int version ) throws Exception {
153
+ private void addClusterNodesToDesiredNodesWithProcessorsOrProcessorRanges (int version , ProcessorsPrecision processorsPrecision )
154
+ throws Exception {
81
155
final List <DesiredNode > nodes ;
82
156
if (randomBoolean ()) {
83
157
nodes = getNodeNames ().stream ()
84
158
.map (
85
159
nodeName -> new DesiredNode (
86
160
Settings .builder ().put (NODE_NAME_SETTING .getKey (), nodeName ).build (),
87
- 0.5f ,
161
+ processorsPrecision == ProcessorsPrecision . DOUBLE ? randomDoubleProcessorCount () : randomFloatProcessorCount () ,
88
162
ByteSizeValue .ofGb (randomIntBetween (10 , 24 )),
89
163
ByteSizeValue .ofGb (randomIntBetween (128 , 256 )),
90
164
Version .CURRENT
91
165
)
92
166
)
93
167
.toList ();
94
168
} else {
95
- nodes = getNodeNames ().stream ()
96
- .map (
97
- nodeName -> new DesiredNode (
98
- Settings .builder ().put (NODE_NAME_SETTING .getKey (), nodeName ).build (),
99
- new DesiredNode .ProcessorsRange (randomIntBetween (1 , 10 ), (float ) randomIntBetween (20 , 30 )),
100
- ByteSizeValue .ofGb (randomIntBetween (10 , 24 )),
101
- ByteSizeValue .ofGb (randomIntBetween (128 , 256 )),
102
- Version .CURRENT
103
- )
104
- )
105
- .toList ();
169
+ nodes = getNodeNames ().stream ().map (nodeName -> {
170
+ double minProcessors = processorsPrecision == ProcessorsPrecision .DOUBLE
171
+ ? randomDoubleProcessorCount ()
172
+ : randomFloatProcessorCount ();
173
+ return new DesiredNode (
174
+ Settings .builder ().put (NODE_NAME_SETTING .getKey (), nodeName ).build (),
175
+ new DesiredNode .ProcessorsRange (minProcessors , minProcessors + randomIntBetween (10 , 20 )),
176
+ ByteSizeValue .ofGb (randomIntBetween (10 , 24 )),
177
+ ByteSizeValue .ofGb (randomIntBetween (128 , 256 )),
178
+ Version .CURRENT
179
+ );
180
+ }).toList ();
106
181
}
107
182
updateDesiredNodes (nodes , version );
108
183
}
@@ -123,7 +198,7 @@ private void addClusterNodesToDesiredNodesWithIntegerProcessors(int version) thr
123
198
}
124
199
125
200
private void updateDesiredNodes (List <DesiredNode > nodes , int version ) throws IOException {
126
- final var request = new Request ("PUT" , "/_internal/desired_nodes/history /" + version );
201
+ final var request = new Request ("PUT" , "/_internal/desired_nodes/upgrade_test /" + version );
127
202
try (var builder = JsonXContent .contentBuilder ()) {
128
203
builder .startObject ();
129
204
builder .xContentList (UpdateDesiredNodesRequest .NODES_FIELD .getPreferredName (), nodes );
@@ -149,6 +224,14 @@ private List<String> getNodeNames() throws Exception {
149
224
return nodeNames ;
150
225
}
151
226
227
+ private double randomDoubleProcessorCount () {
228
+ return randomDoubleBetween (0.5 , 512.1234 , true );
229
+ }
230
+
231
+ private float randomFloatProcessorCount () {
232
+ return randomIntBetween (1 , 512 ) + randomFloat ();
233
+ }
234
+
152
235
@ SuppressWarnings ("unchecked" )
153
236
private static <T > T extractValue (Map <String , Object > map , String path ) {
154
237
return (T ) XContentMapValues .extractValue (path , map );
0 commit comments