@@ -134,6 +134,11 @@ private void assertMasterNode(Client client, String node) {
134134
135135 public static void writeJSONFile (String node , String json , Logger logger , Long version ) throws Exception {
136136 FileSettingsService fileSettingsService = internalCluster ().getInstance (FileSettingsService .class , node );
137+ writeJSONFile (node , json , logger , version , fileSettingsService .watchedFile ());
138+ }
139+
140+ public static void writeJSONFile (String node , String json , Logger logger , Long version , Path targetPath ) throws Exception {
141+ FileSettingsService fileSettingsService = internalCluster ().getInstance (FileSettingsService .class , node );
137142
138143 Files .createDirectories (fileSettingsService .watchedFileDir ());
139144 Path tempFilePath = createTempFile ();
@@ -147,8 +152,8 @@ public static void writeJSONFile(String node, String json, Logger logger, Long v
147152 do {
148153 try {
149154 // this can fail on Windows because of timing
150- Files .move (tempFilePath , fileSettingsService . watchedFile () , StandardCopyOption .ATOMIC_MOVE );
151- logger .info ("--> after writing JSON config to node {} with path {}" , node , tempFilePath );
155+ Files .move (tempFilePath , targetPath , StandardCopyOption .ATOMIC_MOVE );
156+ logger .info ("--> after writing JSON config to node {} with path {}" , node , targetPath );
152157 return ;
153158 } catch (IOException e ) {
154159 logger .info ("--> retrying writing a settings file [{}]" , retryCount );
@@ -498,6 +503,57 @@ public void testSettingsAppliedOnMasterReElection() throws Exception {
498503 assertClusterStateSaveOK (savedClusterState .v1 (), savedClusterState .v2 (), "43mb" );
499504 }
500505
506+ public void testSymlinkUpdateTriggerReload () throws Exception {
507+ internalCluster ().setBootstrapMasterNodeIndex (0 );
508+ logger .info ("--> start data node / non master node" );
509+ String dataNode = internalCluster ().startNode (Settings .builder ().put (dataOnlyNode ()).put ("discovery.initial_state_timeout" , "1s" ));
510+ FileSettingsService dataFileSettingsService = internalCluster ().getInstance (FileSettingsService .class , dataNode );
511+
512+ assertFalse (dataFileSettingsService .watching ());
513+
514+ logger .info ("--> start master node" );
515+ final String masterNode = internalCluster ().startMasterOnlyNode ();
516+ assertMasterNode (internalCluster ().nonMasterClient (), masterNode );
517+ {
518+ var savedClusterState = setupClusterStateListener (masterNode );
519+
520+ FileSettingsService masterFileSettingsService = internalCluster ().getInstance (FileSettingsService .class , masterNode );
521+
522+ assertBusy (() -> assertTrue (masterFileSettingsService .watching ()));
523+ assertFalse (dataFileSettingsService .watching ());
524+
525+ // Create the settings.json as a symlink to simulate k8 setup
526+ // settings.json -> ..data/settings.json
527+ // ..data -> ..TIMESTAMP_TEMP_FOLDER_1
528+ createK8sLikeSymlinks (masterNode );
529+ assertClusterStateSaveOK (savedClusterState .v1 (), savedClusterState .v2 (), "50mb" );
530+ }
531+ {
532+ var savedClusterState = setupClusterStateListener (masterNode );
533+ // Update ..data symlink to ..data -> ..TIMESTAMP_TEMP_FOLDER_2 to simulate kubernetes secret update
534+ updateSymlinks (masterNode , testJSON43mb );
535+ assertClusterStateSaveOK (savedClusterState .v1 (), savedClusterState .v2 (), "43mb" );
536+ }
537+ }
538+
539+ public Path createK8sLikeSymlinks (String node ) throws Exception {
540+ FileSettingsService fileSettingsService = internalCluster ().getInstance (FileSettingsService .class , node );
541+ Path baseDir = fileSettingsService .watchedFileDir ();
542+ var fileDir = Files .createDirectories (baseDir .resolve ("..TIMESTAMP_TEMP_FOLDER_1" ));
543+ writeJSONFile (node , testJSON , logger , versionCounter .incrementAndGet (), fileDir .resolve ("settings.json" ));
544+ var dataDir = Files .createSymbolicLink (baseDir .resolve ("..data" ), fileDir .getFileName ());
545+ return Files .createSymbolicLink (baseDir .resolve ("settings.json" ), dataDir .getFileName ().resolve ("settings.json" ));
546+ }
547+
548+ public void updateSymlinks (String node , String json ) throws Exception {
549+ FileSettingsService fileSettingsService = internalCluster ().getInstance (FileSettingsService .class , node );
550+ Path baseDir = fileSettingsService .watchedFileDir ();
551+ var fileDir = Files .createDirectories (baseDir .resolve ("..TIMESTAMP_TEMP_FOLDER_2" ));
552+ writeJSONFile (node , json , logger , versionCounter .incrementAndGet (), fileDir .resolve ("settings.json" ));
553+ Files .deleteIfExists (baseDir .resolve ("..data" ));
554+ Files .createSymbolicLink (baseDir .resolve ("..data" ), fileDir .getFileName ());
555+ }
556+
501557 private void assertHasErrors (AtomicLong waitForMetadataVersion , String expectedError ) {
502558 var errorMetadata = getErrorMetadata (waitForMetadataVersion );
503559 assertThat (errorMetadata , is (notNullValue ()));
0 commit comments