github.com/cilium/cilium@v1.16.2/pkg/hubble/exporter/config_watcher_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package exporter
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	"github.com/cilium/cilium/api/v1/flow"
    13  	"github.com/cilium/cilium/pkg/time"
    14  )
    15  
    16  func TestYamlConfigFileUnmarshalling(t *testing.T) {
    17  	// given
    18  	fileName := "testdata/valid-flowlogs-config.yaml"
    19  
    20  	sut := configWatcher{configFilePath: fileName}
    21  
    22  	// when
    23  	config, hash, err := sut.readConfig()
    24  	assert.NoError(t, err)
    25  
    26  	// then
    27  	assert.Equal(t, 3, len(config.FlowLogs))
    28  
    29  	assert.Equal(t, uint64(0x31b7b661343ab32f), hash)
    30  
    31  	expectedDate := time.Date(2023, 10, 9, 23, 59, 59, 0, time.FixedZone("", -7*60*60))
    32  
    33  	expectedConfigs := []FlowLogConfig{
    34  		{
    35  			Name:           "test001",
    36  			FilePath:       "/var/log/network/flow-log/pa/test001.log",
    37  			FieldMask:      FieldMask{},
    38  			IncludeFilters: FlowFilters{},
    39  			ExcludeFilters: FlowFilters{},
    40  			End:            &expectedDate,
    41  		},
    42  		{
    43  			Name:      "test002",
    44  			FilePath:  "/var/log/network/flow-log/pa/test002.log",
    45  			FieldMask: FieldMask{"source.namespace", "source.pod_name", "destination.namespace", "destination.pod_name", "verdict"},
    46  			IncludeFilters: FlowFilters{
    47  				{
    48  					SourcePod: []string{"default/"},
    49  					EventType: []*flow.EventTypeFilter{
    50  						{Type: 1},
    51  					},
    52  				},
    53  				{
    54  					DestinationPod: []string{"frontend/nginx-975996d4c-7hhgt"},
    55  				},
    56  			},
    57  			ExcludeFilters: FlowFilters{},
    58  			End:            &expectedDate,
    59  		},
    60  		{
    61  			Name:           "test003",
    62  			FilePath:       "/var/log/network/flow-log/pa/test003.log",
    63  			FieldMask:      FieldMask{"source", "destination", "verdict"},
    64  			IncludeFilters: FlowFilters{},
    65  			ExcludeFilters: FlowFilters{
    66  				{
    67  					DestinationPod: []string{"ingress/"},
    68  				},
    69  			},
    70  			End: nil,
    71  		},
    72  	}
    73  
    74  	for i := range expectedConfigs {
    75  		assertFlowLogConfig(t, expectedConfigs[i], *config.FlowLogs[i])
    76  	}
    77  }
    78  
    79  func TestEmptyYamlConfigFileUnmarshalling(t *testing.T) {
    80  	// given
    81  	fileName := "testdata/empty-flowlogs-config.yaml"
    82  
    83  	sut := configWatcher{configFilePath: fileName}
    84  
    85  	// when
    86  	config, hash, err := sut.readConfig()
    87  	assert.NoError(t, err)
    88  
    89  	// then
    90  	assert.Equal(t, 0, len(config.FlowLogs))
    91  	assert.Equal(t, uint64(0x4b2008fd98c1dd4), hash)
    92  }
    93  
    94  func TestInvalidConfigFile(t *testing.T) {
    95  	cases := []struct {
    96  		name             string
    97  		watcher          *configWatcher
    98  		expectedErrorMsg string
    99  	}{
   100  		{
   101  			name:             "missing file",
   102  			watcher:          &configWatcher{configFilePath: "non-existing-file-name"},
   103  			expectedErrorMsg: "cannot read file",
   104  		},
   105  		{
   106  			name:             "invalid yaml",
   107  			watcher:          &configWatcher{configFilePath: "testdata/invalid-flowlogs-config.yaml"},
   108  			expectedErrorMsg: "cannot parse yaml",
   109  		},
   110  		{
   111  			name:             "duplicated name",
   112  			watcher:          &configWatcher{configFilePath: "testdata/duplicate-names-flowlogs-config.yaml"},
   113  			expectedErrorMsg: "invalid yaml config file: duplicated flowlog name test001",
   114  		},
   115  		{
   116  			name:             "duplicated path",
   117  			watcher:          &configWatcher{configFilePath: "testdata/duplicate-paths-flowlogs-config.yaml"},
   118  			expectedErrorMsg: "invalid yaml config file: duplicated flowlog path /var/log/network/flow-log/pa/test001.log",
   119  		},
   120  	}
   121  
   122  	for _, tc := range cases {
   123  		t.Run(tc.name, func(t *testing.T) {
   124  			config, _, err := tc.watcher.readConfig()
   125  			assert.Nil(t, config)
   126  			assert.Contains(t, err.Error(), tc.expectedErrorMsg)
   127  		})
   128  	}
   129  }
   130  
   131  func TestReloadNotificationReceived(t *testing.T) {
   132  	// given
   133  	fileName := "testdata/valid-flowlogs-config.yaml"
   134  
   135  	configReceived := false
   136  
   137  	// when
   138  	reloadInterval = 1 * time.Millisecond
   139  	sut := NewConfigWatcher(fileName, func(_ context.Context, _ uint64, config DynamicExportersConfig) {
   140  		configReceived = true
   141  	})
   142  	defer sut.Stop()
   143  
   144  	// then
   145  	assert.Eventually(t, func() bool {
   146  		return configReceived
   147  	}, 1*time.Second, 1*time.Millisecond)
   148  
   149  }
   150  
   151  func assertFlowLogConfig(t *testing.T, expected, actual FlowLogConfig) {
   152  
   153  	assert.Equal(t, expected.Name, actual.Name)
   154  	assert.Equal(t, expected.FilePath, actual.FilePath)
   155  	assert.Equal(t, expected.FieldMask, actual.FieldMask)
   156  	assert.Equal(t, len(expected.IncludeFilters), len(actual.IncludeFilters))
   157  	for i := range expected.IncludeFilters {
   158  		assert.Equal(t, expected.IncludeFilters[i].String(), actual.IncludeFilters[i].String())
   159  	}
   160  	assert.Equal(t, len(expected.ExcludeFilters), len(actual.ExcludeFilters))
   161  	for i := range expected.ExcludeFilters {
   162  		assert.Equal(t, expected.ExcludeFilters[i].String(), actual.ExcludeFilters[i].String())
   163  	}
   164  	if expected.End == nil {
   165  		assert.Nil(t, actual.End)
   166  	} else {
   167  		assert.True(t, expected.End.Equal(*actual.End), "expected %s vs actual %s", expected.End.String(), actual.End.String())
   168  	}
   169  
   170  }