github.com/Jeffail/benthos/v3@v3.65.0/internal/config/reader_test.go (about)

     1  package config
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/Jeffail/benthos/v3/lib/log"
    10  	"github.com/Jeffail/benthos/v3/lib/manager"
    11  	"github.com/Jeffail/benthos/v3/lib/metrics"
    12  	"github.com/Jeffail/benthos/v3/lib/stream"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func newDummyReader(confFilePath string) *Reader {
    18  	rdr := NewReader(confFilePath, nil)
    19  	rdr.changeDelayPeriod = 1 * time.Millisecond
    20  	rdr.changeFlushPeriod = 1 * time.Millisecond
    21  	return rdr
    22  }
    23  
    24  func TestReaderFileWatching(t *testing.T) {
    25  	dummyConfig := []byte(`
    26  input:
    27    kafka: {}
    28  output:
    29    aws_s3: {}
    30  `)
    31  
    32  	confDir := t.TempDir()
    33  
    34  	// Create an empty config file in the config folder
    35  	confFilePath := filepath.Join(confDir, "main.yaml")
    36  	require.NoError(t, os.WriteFile(confFilePath, []byte{}, 0o644))
    37  
    38  	rdr := newDummyReader(confFilePath)
    39  
    40  	changeChan := make(chan struct{})
    41  	var updatedConf stream.Config
    42  	require.NoError(t, rdr.SubscribeConfigChanges(func(conf stream.Config) bool {
    43  		updatedConf = conf
    44  		close(changeChan)
    45  		return true
    46  	}))
    47  
    48  	// Watch for configuration changes
    49  	testMgr, err := manager.NewV2(manager.NewResourceConfig(), nil, log.Noop(), metrics.Noop())
    50  	require.NoError(t, err)
    51  	require.NoError(t, rdr.BeginFileWatching(testMgr, true))
    52  
    53  	// Overwrite original config
    54  	require.NoError(t, os.WriteFile(confFilePath, dummyConfig, 0o644))
    55  
    56  	// Wait for the config watcher to reload the config
    57  	select {
    58  	case <-changeChan:
    59  	case <-time.After(100 * time.Millisecond):
    60  		require.FailNow(t, "Expected a config change to be triggered")
    61  	}
    62  
    63  	assert.Equal(t, "kafka", updatedConf.Input.Type)
    64  	assert.Equal(t, "aws_s3", updatedConf.Output.Type)
    65  }
    66  
    67  func TestReaderFileWatchingSymlinkReplace(t *testing.T) {
    68  	dummyConfig := []byte(`
    69  input:
    70    kafka: {}
    71  output:
    72    aws_s3: {}
    73  `)
    74  
    75  	rootDir := t.TempDir()
    76  
    77  	// Create a config folder
    78  	confDir := filepath.Join(rootDir, "config")
    79  	require.NoError(t, os.Mkdir(confDir, 0o755))
    80  
    81  	// Create a symlink to the config folder
    82  	confDirSymlink := filepath.Join(rootDir, "symlink")
    83  	require.NoError(t, os.Symlink(confDir, confDirSymlink))
    84  
    85  	// Create an empty config file in the config folder through the symlink
    86  	confFilePath := filepath.Join(confDirSymlink, "main.yaml")
    87  	require.NoError(t, os.WriteFile(confFilePath, []byte{}, 0o644))
    88  
    89  	rdr := newDummyReader(confFilePath)
    90  
    91  	changeChan := make(chan struct{})
    92  	var updatedConf stream.Config
    93  	require.NoError(t, rdr.SubscribeConfigChanges(func(conf stream.Config) bool {
    94  		updatedConf = conf
    95  		close(changeChan)
    96  		return true
    97  	}))
    98  
    99  	// Watch for configuration changes
   100  	testMgr, err := manager.NewV2(manager.NewResourceConfig(), nil, log.Noop(), metrics.Noop())
   101  	require.NoError(t, err)
   102  	require.NoError(t, rdr.BeginFileWatching(testMgr, true))
   103  
   104  	// Create a new config folder and place in it a new copy of the config file
   105  	newConfDir := filepath.Join(rootDir, "config_new")
   106  	require.NoError(t, os.Mkdir(newConfDir, 0o755))
   107  	require.NoError(t, os.WriteFile(filepath.Join(newConfDir, "main.yaml"), dummyConfig, 0o644))
   108  
   109  	// Create a symlink to the new config folder
   110  	newConfDirSymlink := filepath.Join(rootDir, "symlink_new")
   111  	require.NoError(t, os.Symlink(newConfDir, newConfDirSymlink))
   112  
   113  	// Overwrite the original symlink with the new symlink
   114  	require.NoError(t, os.Rename(newConfDirSymlink, confDirSymlink))
   115  
   116  	// Remove the original config folder to trigger a config refresh
   117  	require.NoError(t, os.RemoveAll(confDir))
   118  
   119  	// Wait for the config watcher to reload the config
   120  	select {
   121  	case <-changeChan:
   122  	case <-time.After(100 * time.Millisecond):
   123  		require.FailNow(t, "Expected a config change to be triggered")
   124  	}
   125  
   126  	assert.Equal(t, "kafka", updatedConf.Input.Type)
   127  	assert.Equal(t, "aws_s3", updatedConf.Output.Type)
   128  }