88import org .elasticsearch .Version ;
99import org .elasticsearch .cluster .metadata .IndexMetaData ;
1010import org .elasticsearch .cluster .metadata .IndexMetaData .State ;
11- import org .elasticsearch .common .collect .Tuple ;
1211import org .elasticsearch .common .settings .Settings ;
1312import org .elasticsearch .index .IndexSettings ;
1413import org .elasticsearch .index .MapperTestUtils ;
1514import org .elasticsearch .index .mapper .MapperService ;
1615import org .elasticsearch .test .ESTestCase ;
16+ import org .elasticsearch .xpack .ccr .CcrSettings ;
1717import org .elasticsearch .xpack .ccr .ShardChangesIT ;
1818
1919import java .io .IOException ;
@@ -31,42 +31,44 @@ public void testValidation() throws IOException {
3131 }
3232 {
3333 // should fail, because follow index does not exist
34- IndexMetaData leaderIMD = createIMD ("index1" , 5 );
34+ IndexMetaData leaderIMD = createIMD ("index1" , 5 , Settings . EMPTY );
3535 Exception e = expectThrows (IllegalArgumentException .class , () -> FollowIndexAction .validate (request , leaderIMD , null , null ));
3636 assertThat (e .getMessage (), equalTo ("follow index [index2] does not exist" ));
3737 }
3838 {
3939 // 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 );
4242 Exception e = expectThrows (IllegalArgumentException .class ,
4343 () -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
4444 assertThat (e .getMessage (), equalTo ("leader index [index1] does not have soft deletes enabled" ));
4545 }
4646 {
4747 // 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 );
5051 Exception e = expectThrows (IllegalArgumentException .class ,
5152 () -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
5253 assertThat (e .getMessage (),
5354 equalTo ("leader index primary shards [5] does not match with the number of shards of the follow index [4]" ));
5455 }
5556 {
5657 // 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 ( ));
6162 Exception e = expectThrows (IllegalArgumentException .class ,
6263 () -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
6364 assertThat (e .getMessage (), equalTo ("leader and follow index must be open" ));
6465 }
6566 {
6667 // should fail, because leader has a field with the same name mapped as keyword and follower as text
6768 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 ());
7072 MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (), Settings .EMPTY , "index2" );
7173 mapperService .updateMapping (followIMD );
7274 Exception e = expectThrows (IllegalArgumentException .class ,
@@ -76,35 +78,54 @@ public void testValidation() throws IOException {
7678 {
7779 // should fail because of non whitelisted settings not the same between leader and follow index
7880 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 ());
8689 Exception e = expectThrows (IllegalArgumentException .class ,
8790 () -> FollowIndexAction .validate (request , leaderIMD , followIMD , null ));
8891 assertThat (e .getMessage (), equalTo ("the leader and follower index settings must be identical" ));
8992 }
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+ }
90108 {
91109 // 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 ());
94114 MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (), Settings .EMPTY , "index2" );
95115 mapperService .updateMapping (followIMD );
96116 FollowIndexAction .validate (request , leaderIMD , followIMD , mapperService );
97117 }
98118 {
99119 // should succeed, index settings are identical
100120 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 ());
108129 MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (),
109130 followIMD .getSettings (), "index2" );
110131 mapperService .updateMapping (followIMD );
@@ -113,37 +134,35 @@ public void testValidation() throws IOException {
113134 {
114135 // should succeed despite whitelisted settings being different
115136 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 ());
125147 MapperService mapperService = MapperTestUtils .newMapperService (xContentRegistry (), createTempDir (),
126148 followIMD .getSettings (), "index2" );
127149 mapperService .updateMapping (followIMD );
128150 FollowIndexAction .validate (request , leaderIMD , followIMD , mapperService );
129151 }
130152 }
131153
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 );
134156 }
135157
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 )
144163 .state (state )
145164 .numberOfReplicas (0 )
146- .setRoutingNumShards (numShards )
165+ .setRoutingNumShards (numberOfShards )
147166 .putMapping ("_doc" , mapping )
148167 .build ();
149168 }
0 commit comments