8
8
import org .elasticsearch .Version ;
9
9
import org .elasticsearch .cluster .metadata .IndexMetaData ;
10
10
import org .elasticsearch .cluster .metadata .IndexMetaData .State ;
11
- import org .elasticsearch .common .collect .Tuple ;
12
11
import org .elasticsearch .common .settings .Settings ;
13
12
import org .elasticsearch .index .IndexSettings ;
14
13
import org .elasticsearch .index .MapperTestUtils ;
15
14
import org .elasticsearch .index .mapper .MapperService ;
16
15
import org .elasticsearch .test .ESTestCase ;
16
+ import org .elasticsearch .xpack .ccr .CcrSettings ;
17
17
import org .elasticsearch .xpack .ccr .ShardChangesIT ;
18
18
19
19
import java .io .IOException ;
@@ -31,42 +31,44 @@ public void testValidation() throws IOException {
31
31
}
32
32
{
33
33
// should fail, because follow index does not exist
34
- IndexMetaData leaderIMD = createIMD ("index1" , 5 );
34
+ IndexMetaData leaderIMD = createIMD ("index1" , 5 , Settings . EMPTY );
35
35
Exception e = expectThrows (IllegalArgumentException .class , () -> FollowIndexAction .validate (request , leaderIMD , null , null ));
36
36
assertThat (e .getMessage (), equalTo ("follow index [index2] does not exist" ));
37
37
}
38
38
{
39
39
// should fail because leader index does not have soft deletes enabled
40
- IndexMetaData leaderIMD = createIMD ("index1" , 5 );
41
- IndexMetaData followIMD = createIMD ("index2" , 5 );
40
+ IndexMetaData leaderIMD = createIMD ("index1" , 5 , Settings . EMPTY );
41
+ IndexMetaData followIMD = createIMD ("index2" , 5 , Settings . EMPTY );
42
42
Exception e = expectThrows (IllegalArgumentException .class ,
43
43
() -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
44
44
assertThat (e .getMessage (), equalTo ("leader index [index1] does not have soft deletes enabled" ));
45
45
}
46
46
{
47
47
// should fail because the number of primary shards between leader and follow index are not equal
48
- IndexMetaData leaderIMD = createIMD ("index1" , 5 , new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ));
49
- IndexMetaData followIMD = createIMD ("index2" , 4 );
48
+ IndexMetaData leaderIMD = createIMD ("index1" , 5 , Settings .builder ()
49
+ .put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ).build ());
50
+ IndexMetaData followIMD = createIMD ("index2" , 4 , Settings .EMPTY );
50
51
Exception e = expectThrows (IllegalArgumentException .class ,
51
52
() -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
52
53
assertThat (e .getMessage (),
53
54
equalTo ("leader index primary shards [5] does not match with the number of shards of the follow index [4]" ));
54
55
}
55
56
{
56
57
// should fail, because leader index is closed
57
- IndexMetaData leaderIMD = createIMD ("index1" , State .CLOSE , "{}" , 5 ,
58
- new Tuple <> (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ));
59
- IndexMetaData followIMD = createIMD ("index2" , State .OPEN , "{}" , 5 ,
60
- new Tuple <> (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ));
58
+ IndexMetaData leaderIMD = createIMD ("index1" , State .CLOSE , "{}" , 5 , Settings . builder ()
59
+ . put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ). build ( ));
60
+ IndexMetaData followIMD = createIMD ("index2" , State .OPEN , "{}" , 5 , Settings . builder ()
61
+ . put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ). build ( ));
61
62
Exception e = expectThrows (IllegalArgumentException .class ,
62
63
() -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
63
64
assertThat (e .getMessage (), equalTo ("leader and follow index must be open" ));
64
65
}
65
66
{
66
67
// should fail, because leader has a field with the same name mapped as keyword and follower as text
67
68
IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , "{\" properties\" : {\" field\" : {\" type\" : \" keyword\" }}}" , 5 ,
68
- new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ));
69
- IndexMetaData followIMD = createIMD ("index2" , State .OPEN , "{\" properties\" : {\" field\" : {\" type\" : \" text\" }}}" , 5 );
69
+ Settings .builder ().put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ).build ());
70
+ IndexMetaData followIMD = createIMD ("index2" , State .OPEN , "{\" properties\" : {\" field\" : {\" type\" : \" text\" }}}" , 5 ,
71
+ Settings .builder ().put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), true ).build ());
70
72
MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (), Settings .EMPTY , "index2" );
71
73
mapperService .updateMapping (followIMD );
72
74
Exception e = expectThrows (IllegalArgumentException .class ,
@@ -76,35 +78,54 @@ public void testValidation() throws IOException {
76
78
{
77
79
// should fail because of non whitelisted settings not the same between leader and follow index
78
80
String mapping = "{\" properties\" : {\" field\" : {\" type\" : \" text\" , \" analyzer\" : \" my_analyzer\" }}}" ;
79
- IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 ,
80
- new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ),
81
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
82
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "whitespace" ));
83
- IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 ,
84
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
85
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ));
81
+ IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 , Settings .builder ()
82
+ .put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" )
83
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
84
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "whitespace" ).build ());
85
+ IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 , Settings .builder ()
86
+ .put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), true )
87
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
88
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ).build ());
86
89
Exception e = expectThrows (IllegalArgumentException .class ,
87
90
() -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
88
91
assertThat (e .getMessage (), equalTo ("the leader and follower index settings must be identical" ));
89
92
}
93
+ {
94
+ // should fail because the following index does not have the following_index settings
95
+ IndexMetaData leaderIMD = createIMD ("index1" , 5 ,
96
+ Settings .builder ().put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ).build ());
97
+ Settings followingIndexSettings = randomBoolean () ? Settings .EMPTY :
98
+ Settings .builder ().put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), false ).build ();
99
+ IndexMetaData followIMD = createIMD ("index2" , 5 , followingIndexSettings );
100
+ MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (),
101
+ followingIndexSettings , "index2" );
102
+ mapperService .updateMapping (followIMD );
103
+ IllegalArgumentException error = expectThrows (IllegalArgumentException .class ,
104
+ () -> FollowIndexAction .validate (request , leaderIMD , followIMD , mapperService ));
105
+ assertThat (error .getMessage (), equalTo ("the following index [index2] is not ready to follow; " +
106
+ "the setting [index.xpack.ccr.following_index] must be enabled." ));
107
+ }
90
108
{
91
109
// should succeed
92
- IndexMetaData leaderIMD = createIMD ("index1" , 5 , new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ));
93
- IndexMetaData followIMD = createIMD ("index2" , 5 );
110
+ IndexMetaData leaderIMD = createIMD ("index1" , 5 , Settings .builder ()
111
+ .put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ).build ());
112
+ IndexMetaData followIMD = createIMD ("index2" , 5 , Settings .builder ()
113
+ .put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), true ).build ());
94
114
MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (), Settings .EMPTY , "index2" );
95
115
mapperService .updateMapping (followIMD );
96
116
FollowIndexAction .validate (request , leaderIMD , followIMD , mapperService );
97
117
}
98
118
{
99
119
// should succeed, index settings are identical
100
120
String mapping = "{\" properties\" : {\" field\" : {\" type\" : \" text\" , \" analyzer\" : \" my_analyzer\" }}}" ;
101
- IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 ,
102
- new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ),
103
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
104
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ));
105
- IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 ,
106
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
107
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ));
121
+ IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 , Settings .builder ()
122
+ .put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" )
123
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
124
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ).build ());
125
+ IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 , Settings .builder ()
126
+ .put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), true )
127
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
128
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ).build ());
108
129
MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (),
109
130
followIMD .getSettings (), "index2" );
110
131
mapperService .updateMapping (followIMD );
@@ -113,37 +134,35 @@ public void testValidation() throws IOException {
113
134
{
114
135
// should succeed despite whitelisted settings being different
115
136
String mapping = "{\" properties\" : {\" field\" : {\" type\" : \" text\" , \" analyzer\" : \" my_analyzer\" }}}" ;
116
- IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 ,
117
- new Tuple <>(IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" ),
118
- new Tuple <>(IndexSettings .INDEX_REFRESH_INTERVAL_SETTING .getKey (), "1s" ),
119
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
120
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ));
121
- IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 ,
122
- new Tuple <>(IndexSettings .INDEX_REFRESH_INTERVAL_SETTING .getKey (), "10s" ),
123
- new Tuple <>("index.analysis.analyzer.my_analyzer.type" , "custom" ),
124
- new Tuple <>("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ));
137
+ IndexMetaData leaderIMD = createIMD ("index1" , State .OPEN , mapping , 5 , Settings .builder ()
138
+ .put (IndexSettings .INDEX_SOFT_DELETES_SETTING .getKey (), "true" )
139
+ .put (IndexSettings .INDEX_REFRESH_INTERVAL_SETTING .getKey (), "1s" )
140
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
141
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ).build ());
142
+ IndexMetaData followIMD = createIMD ("index2" , State .OPEN , mapping , 5 , Settings .builder ()
143
+ .put (CcrSettings .CCR_FOLLOWING_INDEX_SETTING .getKey (), true )
144
+ .put (IndexSettings .INDEX_REFRESH_INTERVAL_SETTING .getKey (), "10s" )
145
+ .put ("index.analysis.analyzer.my_analyzer.type" , "custom" )
146
+ .put ("index.analysis.analyzer.my_analyzer.tokenizer" , "standard" ).build ());
125
147
MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (),
126
148
followIMD .getSettings (), "index2" );
127
149
mapperService .updateMapping (followIMD );
128
150
FollowIndexAction .validate (request , leaderIMD , followIMD , mapperService );
129
151
}
130
152
}
131
153
132
- private static IndexMetaData createIMD (String index , int numShards , Tuple <?, ?>... settings ) throws IOException {
133
- return createIMD (index , State .OPEN , "{\" properties\" : {}}" , numShards , settings );
154
+ private static IndexMetaData createIMD (String index , int numberOfShards , Settings settings ) throws IOException {
155
+ return createIMD (index , State .OPEN , "{\" properties\" : {}}" , numberOfShards , settings );
134
156
}
135
157
136
- private static IndexMetaData createIMD (String index , State state , String mapping , int numShards ,
137
- Tuple <?, ?>... settings ) throws IOException {
138
- Settings .Builder settingsBuilder = settings (Version .CURRENT );
139
- for (Tuple <?, ?> setting : settings ) {
140
- settingsBuilder .put ((String ) setting .v1 (), (String ) setting .v2 ());
141
- }
142
- return IndexMetaData .builder (index ).settings (settingsBuilder )
143
- .numberOfShards (numShards )
158
+ private static IndexMetaData createIMD (String index , State state , String mapping , int numberOfShards ,
159
+ Settings settings ) throws IOException {
160
+ return IndexMetaData .builder (index )
161
+ .settings (settings (Version .CURRENT ).put (settings ))
162
+ .numberOfShards (numberOfShards )
144
163
.state (state )
145
164
.numberOfReplicas (0 )
146
- .setRoutingNumShards (numShards )
165
+ .setRoutingNumShards (numberOfShards )
147
166
.putMapping ("_doc" , mapping )
148
167
.build ();
149
168
}
0 commit comments