github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/cmd/fluent-bit/config_test.go (about) 1 package main 2 3 import ( 4 "io/ioutil" 5 "net/url" 6 "os" 7 "reflect" 8 "testing" 9 "time" 10 11 "github.com/grafana/dskit/backoff" 12 "github.com/grafana/dskit/flagext" 13 "github.com/prometheus/common/model" 14 "github.com/weaveworks/common/logging" 15 16 "github.com/grafana/loki/clients/pkg/promtail/client" 17 18 lokiflag "github.com/grafana/loki/pkg/util/flagext" 19 ) 20 21 type fakeConfig map[string]string 22 23 func (f fakeConfig) Get(key string) string { 24 return f[key] 25 } 26 27 func Test_parseConfig(t *testing.T) { 28 fileName := createTempLabelMap(t) 29 defer os.Remove(fileName) 30 31 tests := []struct { 32 name string 33 conf map[string]string 34 want *config 35 wantErr bool 36 }{ 37 {"defaults", 38 map[string]string{}, 39 &config{ 40 lineFormat: jsonFormat, 41 clientConfig: client.Config{ 42 URL: mustParseURL("http://localhost:3100/loki/api/v1/push"), 43 BatchSize: defaultClientCfg.BatchSize, 44 BatchWait: defaultClientCfg.BatchWait, 45 Timeout: defaultClientCfg.Timeout, 46 ExternalLabels: lokiflag.LabelSet{LabelSet: model.LabelSet{"job": "fluent-bit"}}, 47 BackoffConfig: defaultClientCfg.BackoffConfig, 48 }, 49 logLevel: mustParseLogLevel("info"), 50 dropSingleKey: true, 51 }, 52 false}, 53 {"setting values", 54 map[string]string{ 55 "URL": "http://somewhere.com:3100/loki/api/v1/push", 56 "TenantID": "my-tenant-id", 57 "LineFormat": "key_value", 58 "LogLevel": "warn", 59 "Labels": `{app="foo"}`, 60 "BatchSize": "100", 61 "BatchWait": "30", 62 "Timeout": "1s", 63 "RemoveKeys": "buzz,fuzz", 64 "LabelKeys": "foo,bar", 65 "DropSingleKey": "false", 66 "MinBackoff": "1ms", 67 "MaxBackoff": "5m", 68 "MaxRetries": "10", 69 }, 70 &config{ 71 lineFormat: kvPairFormat, 72 clientConfig: client.Config{ 73 URL: mustParseURL("http://somewhere.com:3100/loki/api/v1/push"), 74 TenantID: "my-tenant-id", 75 BatchSize: 100, 76 BatchWait: mustParseDuration("30s"), 77 Timeout: mustParseDuration("1s"), 78 ExternalLabels: lokiflag.LabelSet{LabelSet: model.LabelSet{"app": "foo"}}, 79 BackoffConfig: backoff.Config{MinBackoff: mustParseDuration("1ms"), MaxBackoff: mustParseDuration("5m"), MaxRetries: 10}, 80 }, 81 logLevel: mustParseLogLevel("warn"), 82 labelKeys: []string{"foo", "bar"}, 83 removeKeys: []string{"buzz", "fuzz"}, 84 dropSingleKey: false, 85 }, 86 false}, 87 {"with label map", 88 map[string]string{ 89 "URL": "http://somewhere.com:3100/loki/api/v1/push", 90 "LineFormat": "key_value", 91 "LogLevel": "warn", 92 "Labels": `{app="foo"}`, 93 "BatchSize": "100", 94 "BatchWait": "30s", 95 "Timeout": "1s", 96 "RemoveKeys": "buzz,fuzz", 97 "LabelKeys": "foo,bar", 98 "DropSingleKey": "false", 99 "MinBackoff": "1ms", 100 "MaxBackoff": "5m", 101 "MaxRetries": "10", 102 "LabelMapPath": fileName, 103 }, 104 &config{ 105 lineFormat: kvPairFormat, 106 clientConfig: client.Config{ 107 URL: mustParseURL("http://somewhere.com:3100/loki/api/v1/push"), 108 TenantID: "", // empty as not set in fluent-bit plugin config map 109 BatchSize: 100, 110 BatchWait: mustParseDuration("30s"), 111 Timeout: mustParseDuration("1s"), 112 ExternalLabels: lokiflag.LabelSet{LabelSet: model.LabelSet{"app": "foo"}}, 113 BackoffConfig: backoff.Config{MinBackoff: mustParseDuration("1ms"), MaxBackoff: mustParseDuration("5m"), MaxRetries: 10}, 114 }, 115 logLevel: mustParseLogLevel("warn"), 116 labelKeys: nil, 117 removeKeys: []string{"buzz", "fuzz"}, 118 dropSingleKey: false, 119 labelMap: map[string]interface{}{ 120 "kubernetes": map[string]interface{}{ 121 "container_name": "container", 122 "host": "host", 123 "namespace_name": "namespace", 124 "pod_name": "instance", 125 "labels": map[string]interface{}{ 126 "component": "component", 127 "tier": "tier", 128 }, 129 }, 130 "stream": "stream", 131 }, 132 }, 133 false}, 134 {"bad url", map[string]string{"URL": "::doh.com"}, nil, true}, 135 {"bad BatchWait", map[string]string{"BatchWait": "30sa"}, nil, true}, 136 {"bad BatchSize", map[string]string{"BatchSize": "a"}, nil, true}, 137 {"bad Timeout", map[string]string{"Timeout": "1a"}, nil, true}, 138 {"bad labels", map[string]string{"Labels": "a"}, nil, true}, 139 {"bad format", map[string]string{"LineFormat": "a"}, nil, true}, 140 {"bad log level", map[string]string{"LogLevel": "a"}, nil, true}, 141 {"bad drop single key", map[string]string{"DropSingleKey": "a"}, nil, true}, 142 {"bad MinBackoff", map[string]string{"MinBackoff": "1msa"}, nil, true}, 143 {"bad MaxBackoff", map[string]string{"MaxBackoff": "5ma"}, nil, true}, 144 {"bad MaxRetries", map[string]string{"MaxRetries": "a"}, nil, true}, 145 {"bad labelmap file", map[string]string{"LabelMapPath": "a"}, nil, true}, 146 } 147 for _, tt := range tests { 148 t.Run(tt.name, func(t *testing.T) { 149 got, err := parseConfig(fakeConfig(tt.conf)) 150 if (err != nil) != tt.wantErr { 151 t.Errorf("parseConfig() error = %v, wantErr %v", err, tt.wantErr) 152 return 153 } 154 if !tt.wantErr { 155 assertConfig(t, got, tt.want) 156 } 157 }) 158 } 159 } 160 161 func assertConfig(t *testing.T, expected, actual *config) { 162 if expected.clientConfig.BatchSize != actual.clientConfig.BatchSize { 163 t.Errorf("incorrect batch size want:%v got:%v", expected.clientConfig.BatchSize, actual.clientConfig.BatchSize) 164 } 165 if !reflect.DeepEqual(expected.clientConfig.ExternalLabels, actual.clientConfig.ExternalLabels) { 166 t.Errorf("incorrect labels want:%v got:%v", expected.clientConfig.ExternalLabels, actual.clientConfig.ExternalLabels) 167 } 168 if expected.clientConfig.BatchWait != actual.clientConfig.BatchWait { 169 t.Errorf("incorrect batch wait want:%v got:%v", expected.clientConfig.BatchWait, actual.clientConfig.BatchWait) 170 } 171 if expected.clientConfig.Timeout != actual.clientConfig.Timeout { 172 t.Errorf("incorrect Timeout want:%v got:%v", expected.clientConfig.Timeout, actual.clientConfig.Timeout) 173 } 174 if expected.clientConfig.BackoffConfig.MinBackoff != actual.clientConfig.BackoffConfig.MinBackoff { 175 t.Errorf("incorrect MinBackoff want:%v got:%v", expected.clientConfig.BackoffConfig.MinBackoff, actual.clientConfig.BackoffConfig.MinBackoff) 176 } 177 if expected.clientConfig.BackoffConfig.MaxBackoff != actual.clientConfig.BackoffConfig.MaxBackoff { 178 t.Errorf("incorrect MaxBackoff want:%v got:%v", expected.clientConfig.BackoffConfig.MaxBackoff, actual.clientConfig.BackoffConfig.MaxBackoff) 179 } 180 if expected.clientConfig.BackoffConfig.MaxRetries != actual.clientConfig.BackoffConfig.MaxRetries { 181 t.Errorf("incorrect MaxRetries want:%v got:%v", expected.clientConfig.BackoffConfig.MaxRetries, actual.clientConfig.BackoffConfig.MaxRetries) 182 } 183 if !reflect.DeepEqual(expected.clientConfig.URL, actual.clientConfig.URL) { 184 t.Errorf("incorrect URL want:%v got:%v", expected.clientConfig.URL, actual.clientConfig.URL) 185 } 186 if !reflect.DeepEqual(expected.clientConfig.TenantID, actual.clientConfig.TenantID) { 187 t.Errorf("incorrect TenantID want:%v got:%v", expected.clientConfig.TenantID, actual.clientConfig.TenantID) 188 } 189 if !reflect.DeepEqual(expected.lineFormat, actual.lineFormat) { 190 t.Errorf("incorrect lineFormat want:%v got:%v", expected.lineFormat, actual.lineFormat) 191 } 192 if !reflect.DeepEqual(expected.removeKeys, actual.removeKeys) { 193 t.Errorf("incorrect removeKeys want:%v got:%v", expected.removeKeys, actual.removeKeys) 194 } 195 if !reflect.DeepEqual(expected.labelKeys, actual.labelKeys) { 196 t.Errorf("incorrect labelKeys want:%v got:%v", expected.labelKeys, actual.labelKeys) 197 } 198 if expected.logLevel.String() != actual.logLevel.String() { 199 t.Errorf("incorrect logLevel want:%v got:%v", expected.logLevel.String(), actual.logLevel.String()) 200 } 201 if !reflect.DeepEqual(expected.labelMap, actual.labelMap) { 202 t.Errorf("incorrect labelMap want:%v got:%v", expected.labelMap, actual.labelMap) 203 } 204 } 205 206 func mustParseURL(u string) flagext.URLValue { 207 parsed, err := url.Parse(u) 208 if err != nil { 209 panic(err) 210 } 211 return flagext.URLValue{URL: parsed} 212 } 213 214 func mustParseLogLevel(l string) logging.Level { 215 level := logging.Level{} 216 err := level.Set(l) 217 if err != nil { 218 panic(err) 219 } 220 return level 221 } 222 223 func mustParseDuration(u string) time.Duration { 224 parsed, err := time.ParseDuration(u) 225 if err != nil { 226 panic(err) 227 } 228 return parsed 229 } 230 231 func createTempLabelMap(t *testing.T) string { 232 file, err := ioutil.TempFile("", "labelmap") 233 if err != nil { 234 t.Fatal(err) 235 } 236 _, err = file.WriteString(`{ 237 "kubernetes": { 238 "namespace_name": "namespace", 239 "labels": { 240 "component": "component", 241 "tier": "tier" 242 }, 243 "host": "host", 244 "container_name": "container", 245 "pod_name": "instance" 246 }, 247 "stream": "stream" 248 }`) 249 if err != nil { 250 t.Fatal(err) 251 } 252 return file.Name() 253 }