1111import org .elasticsearch .ElasticsearchStatusException ;
1212import org .elasticsearch .ResourceAlreadyExistsException ;
1313import org .elasticsearch .action .ActionListener ;
14- import org .elasticsearch .action .admin .indices .delete .DeleteIndexAction ;
15- import org .elasticsearch .action .admin .indices .delete .DeleteIndexRequest ;
1614import org .elasticsearch .action .support .ActionFilters ;
1715import org .elasticsearch .action .support .IndicesOptions ;
1816import org .elasticsearch .action .support .master .TransportMasterNodeAction ;
5048import org .elasticsearch .xpack .core .security .authz .permission .ResourcePrivileges ;
5149import org .elasticsearch .xpack .core .security .support .Exceptions ;
5250import org .elasticsearch .xpack .dataframe .persistence .DataFrameTransformsConfigManager ;
53- import org .elasticsearch .xpack .dataframe .persistence .DataframeIndex ;
5451import org .elasticsearch .xpack .dataframe .transforms .pivot .Pivot ;
5552
5653import java .io .IOException ;
@@ -117,18 +114,6 @@ protected void masterOperation(Request request, ClusterState clusterState, Actio
117114 return ;
118115 }
119116
120- final String [] dest = indexNameExpressionResolver .concreteIndexNames (clusterState ,
121- IndicesOptions .lenientExpandOpen (),
122- config .getDestination ().getIndex ());
123-
124- if (dest .length > 0 ) {
125- listener .onFailure (new ElasticsearchStatusException (
126- DataFrameMessages .getMessage (DataFrameMessages .REST_PUT_DATA_FRAME_DEST_INDEX_ALREADY_EXISTS ,
127- config .getDestination ().getIndex ()),
128- RestStatus .BAD_REQUEST ));
129- return ;
130- }
131-
132117 for (String src : config .getSource ().getIndex ()) {
133118 if (indexNameExpressionResolver .concreteIndexNames (clusterState , IndicesOptions .lenientExpandOpen (), src ).length == 0 ) {
134119 listener .onFailure (new ElasticsearchStatusException (
@@ -145,9 +130,19 @@ protected void masterOperation(Request request, ClusterState clusterState, Actio
145130 .indices (config .getSource ().getIndex ())
146131 .privileges ("read" )
147132 .build ();
133+ String [] destPrivileges = new String [3 ];
134+ destPrivileges [0 ] = "read" ;
135+ destPrivileges [1 ] = "index" ;
136+ // If the destination index does not exist, we can assume that we may have to create it on start.
137+ // We should check that the creating user has the privileges to create the index.
138+ if (indexNameExpressionResolver .concreteIndexNames (clusterState ,
139+ IndicesOptions .lenientExpandOpen (),
140+ config .getDestination ().getIndex ()).length == 0 ) {
141+ destPrivileges [2 ] = "create_index" ;
142+ }
148143 RoleDescriptor .IndicesPrivileges destIndexPrivileges = RoleDescriptor .IndicesPrivileges .builder ()
149144 .indices (config .getDestination ().getIndex ())
150- .privileges ("read" , "index" , "create_index" )
145+ .privileges (destPrivileges )
151146 .build ();
152147
153148 HasPrivilegesRequest privRequest = new HasPrivilegesRequest ();
@@ -202,41 +197,12 @@ private void putDataFrame(DataFrameTransformConfig config, ActionListener<Respon
202197 // <5> Return the listener, or clean up destination index on failure.
203198 ActionListener <Boolean > putTransformConfigurationListener = ActionListener .wrap (
204199 putTransformConfigurationResult -> listener .onResponse (new Response (true )),
205- putTransformConfigurationException ->
206- ClientHelper .executeAsyncWithOrigin (client ,
207- ClientHelper .DATA_FRAME_ORIGIN ,
208- DeleteIndexAction .INSTANCE ,
209- new DeleteIndexRequest (config .getDestination ().getIndex ()), ActionListener .wrap (
210- deleteIndexResponse -> listener .onFailure (putTransformConfigurationException ),
211- deleteIndexException -> {
212- String msg = "Failed to delete destination index after creating transform [" + config .getId () + "] failed" ;
213- listener .onFailure (
214- new ElasticsearchStatusException (msg ,
215- RestStatus .INTERNAL_SERVER_ERROR ,
216- putTransformConfigurationException ));
217- })
218- )
200+ listener ::onFailure
219201 );
220202
221203 // <4> Put our transform
222- ActionListener <Boolean > createDestinationIndexListener = ActionListener .wrap (
223- createIndexResult -> dataFrameTransformsConfigManager .putTransformConfiguration (config , putTransformConfigurationListener ),
224- createDestinationIndexException -> listener .onFailure (
225- new RuntimeException (DataFrameMessages .REST_PUT_DATA_FRAME_FAILED_TO_CREATE_DEST_INDEX ,
226- createDestinationIndexException ))
227- );
228-
229- // <3> Create the destination index
230- ActionListener <Map <String , String >> deduceMappingsListener = ActionListener .wrap (
231- mappings -> DataframeIndex .createDestinationIndex (client , config , mappings , createDestinationIndexListener ),
232- deduceTargetMappingsException -> listener .onFailure (
233- new RuntimeException (DataFrameMessages .REST_PUT_DATA_FRAME_FAILED_TO_DEDUCE_DEST_MAPPINGS ,
234- deduceTargetMappingsException ))
235- );
236-
237- // <2> Deduce our mappings for the destination index
238204 ActionListener <Boolean > pivotValidationListener = ActionListener .wrap (
239- validationResult -> pivot . deduceMappings ( client , deduceMappingsListener ),
205+ validationResult -> dataFrameTransformsConfigManager . putTransformConfiguration ( config , putTransformConfigurationListener ),
240206 validationException -> listener .onFailure (
241207 new RuntimeException (DataFrameMessages .REST_PUT_DATA_FRAME_FAILED_TO_VALIDATE_DATA_FRAME_CONFIGURATION ,
242208 validationException ))
0 commit comments