github.com/Jeffail/benthos/v3@v3.65.0/public/service/config_test.go (about) 1 package service 2 3 import ( 4 "testing" 5 6 "github.com/Jeffail/benthos/v3/internal/docs" 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 "gopkg.in/yaml.v3" 10 ) 11 12 func TestConfigFromStructYAML(t *testing.T) { 13 type confNestedType struct { 14 D bool `yaml:"d"` 15 E string `yaml:"e"` 16 } 17 type confType struct { 18 A string `yaml:"a"` 19 B int `yaml:"b"` 20 C confNestedType `yaml:"c"` 21 } 22 23 spec, err := NewStructConfigSpec(func() interface{} { 24 return &confType{ 25 A: "avalue", 26 B: 11, 27 C: confNestedType{ 28 D: true, 29 E: "evalue", 30 }, 31 } 32 }) 33 require.NoError(t, err) 34 35 tests := []struct { 36 name string 37 config string 38 lints []docs.Lint 39 sanitized string 40 }{ 41 { 42 name: "no fields", 43 config: "{}", 44 sanitized: `a: avalue 45 b: 11 46 c: 47 d: true 48 e: evalue 49 `, 50 }, 51 { 52 name: "fields set", 53 config: `a: newavalue 54 c: 55 d: false 56 `, 57 sanitized: `a: newavalue 58 b: 11 59 c: 60 d: false 61 e: evalue 62 `, 63 }, 64 { 65 name: "fields set unrecognized field", 66 config: `a: newavalue 67 not_real: this doesnt exist in the spec 68 c: 69 d: false 70 `, 71 sanitized: `a: newavalue 72 b: 11 73 c: 74 d: false 75 e: evalue 76 `, 77 lints: []docs.Lint{ 78 docs.NewLintError(2, "field not_real not recognised"), 79 }, 80 }, 81 { 82 name: "fields set nested unrecognized field", 83 config: `a: newavalue 84 c: 85 d: false 86 not_real: this doesnt exist in the spec 87 `, 88 sanitized: `a: newavalue 89 b: 11 90 c: 91 d: false 92 e: evalue 93 `, 94 lints: []docs.Lint{ 95 docs.NewLintError(4, "field not_real not recognised"), 96 }, 97 }, 98 } 99 100 for _, test := range tests { 101 t.Run(test.name, func(t *testing.T) { 102 confBytes := []byte(test.config) 103 104 node, err := getYAMLNode(confBytes) 105 require.NoError(t, err) 106 107 assert.Equal(t, test.lints, spec.component.Config.Children.LintYAML(docs.NewLintContext(), node)) 108 109 pConf, err := spec.configFromNode(nil, node) 110 require.NoError(t, err) 111 112 var sanitNode yaml.Node 113 require.NoError(t, sanitNode.Encode(pConf.AsStruct())) 114 115 require.NoError(t, spec.component.Config.Children.SanitiseYAML(&sanitNode, docs.SanitiseConfig{ 116 RemoveTypeField: true, 117 RemoveDeprecated: true, 118 })) 119 120 sanitConfOutBytes, err := yaml.Marshal(sanitNode) 121 require.NoError(t, err) 122 assert.Equal(t, test.sanitized, string(sanitConfOutBytes)) 123 }) 124 } 125 } 126 127 func TestConfigGeneric(t *testing.T) { 128 spec := NewConfigSpec(). 129 Field(NewStringField("a")). 130 Field(NewIntField("b").Default(11)). 131 Field(NewObjectField("c", 132 NewBoolField("d").Default(true), 133 NewStringField("e").Default("evalue"), 134 )) 135 136 tests := []struct { 137 name string 138 config string 139 lints []docs.Lint 140 sanitized string 141 }{ 142 { 143 name: "no fields except mandatory", 144 config: `a: foovalue`, 145 sanitized: `a: foovalue 146 b: 11 147 c: 148 d: true 149 e: evalue 150 `, 151 }, 152 { 153 name: "fields set", 154 config: `a: newavalue 155 c: 156 d: false 157 `, 158 sanitized: `a: newavalue 159 b: 11 160 c: 161 d: false 162 e: evalue 163 `, 164 }, 165 { 166 name: "fields set unrecognized field", 167 config: `a: newavalue 168 not_real: this doesnt exist in the spec 169 c: 170 d: false 171 `, 172 sanitized: `a: newavalue 173 b: 11 174 c: 175 d: false 176 e: evalue 177 `, 178 lints: []docs.Lint{ 179 docs.NewLintError(2, "field not_real not recognised"), 180 }, 181 }, 182 { 183 name: "fields set nested unrecognized field", 184 config: `a: newavalue 185 c: 186 d: false 187 not_real: this doesnt exist in the spec 188 `, 189 sanitized: `a: newavalue 190 b: 11 191 c: 192 d: false 193 e: evalue 194 `, 195 lints: []docs.Lint{ 196 docs.NewLintError(4, "field not_real not recognised"), 197 }, 198 }, 199 } 200 201 for _, test := range tests { 202 t.Run(test.name, func(t *testing.T) { 203 confBytes := []byte(test.config) 204 205 node, err := getYAMLNode(confBytes) 206 require.NoError(t, err) 207 208 assert.Equal(t, test.lints, spec.component.Config.Children.LintYAML(docs.NewLintContext(), node)) 209 210 pConf, err := spec.configFromNode(nil, node) 211 require.NoError(t, err) 212 213 var sanitNode yaml.Node 214 require.NoError(t, sanitNode.Encode(pConf.generic)) 215 216 require.NoError(t, spec.component.Config.Children.SanitiseYAML(&sanitNode, docs.SanitiseConfig{ 217 RemoveTypeField: true, 218 RemoveDeprecated: true, 219 })) 220 221 sanitConfOutBytes, err := yaml.Marshal(sanitNode) 222 require.NoError(t, err) 223 assert.Equal(t, test.sanitized, string(sanitConfOutBytes)) 224 }) 225 } 226 } 227 228 func TestConfigTypedFields(t *testing.T) { 229 spec := NewConfigSpec(). 230 Field(NewStringField("a")). 231 Field(NewIntField("b").Default(11)). 232 Field(NewObjectField("c", 233 NewBoolField("d").Default(true), 234 NewStringField("e").Default("evalue"), 235 NewObjectField("f", 236 NewIntField("g").Default(12), 237 NewStringField("h"), 238 NewFloatField("i").Default(13.0), 239 NewStringListField("j"), 240 NewStringMapField("k"), 241 NewIntListField("l"), 242 NewIntMapField("m"), 243 ), 244 )) 245 246 parsedConfig, err := spec.ParseYAML(` 247 a: setavalue 248 c: 249 f: 250 g: 22 251 h: sethvalue 252 i: 23.1 253 j: 254 - first in list 255 - second in list 256 k: 257 first: one 258 second: two 259 l: 260 - 11 261 - 12 262 m: 263 first: 21 264 second: 22 265 `, nil) 266 require.NoError(t, err) 267 268 s, err := parsedConfig.FieldString("a") 269 assert.NoError(t, err) 270 assert.Equal(t, "setavalue", s) 271 272 _, err = parsedConfig.FieldString("z") 273 assert.Error(t, err) 274 275 _, err = parsedConfig.FieldInt("c", "z") 276 assert.Error(t, err) 277 278 _, err = parsedConfig.FieldFloat("c", "d", "z") 279 assert.Error(t, err) 280 281 _, err = parsedConfig.FieldBool("c", "z") 282 assert.Error(t, err) 283 284 i, err := parsedConfig.FieldInt("b") 285 assert.NoError(t, err) 286 assert.Equal(t, 11, i) 287 288 b, err := parsedConfig.FieldBool("c", "d") 289 assert.NoError(t, err) 290 assert.Equal(t, true, b) 291 292 i, err = parsedConfig.FieldInt("c", "f", "g") 293 assert.NoError(t, err) 294 assert.Equal(t, 22, i) 295 296 f, err := parsedConfig.FieldFloat("c", "f", "i") 297 assert.NoError(t, err) 298 assert.Equal(t, 23.1, f) 299 300 ll, err := parsedConfig.FieldStringList("c", "f", "j") 301 assert.NoError(t, err) 302 assert.Equal(t, []string{"first in list", "second in list"}, ll) 303 304 sm, err := parsedConfig.FieldStringMap("c", "f", "k") 305 assert.NoError(t, err) 306 assert.Equal(t, map[string]string{"first": "one", "second": "two"}, sm) 307 308 il, err := parsedConfig.FieldIntList("c", "f", "l") 309 assert.NoError(t, err) 310 assert.Equal(t, []int{11, 12}, il) 311 312 im, err := parsedConfig.FieldIntMap("c", "f", "m") 313 assert.NoError(t, err) 314 assert.Equal(t, map[string]int{"first": 21, "second": 22}, im) 315 316 // Testing namespaces 317 nsC := parsedConfig.Namespace("c") 318 nsFOne := nsC.Namespace("f") 319 nsFTwo := parsedConfig.Namespace("c", "f") 320 321 b, err = nsC.FieldBool("d") 322 assert.NoError(t, err) 323 assert.Equal(t, true, b) 324 325 i, err = nsFOne.FieldInt("g") 326 assert.NoError(t, err) 327 assert.Equal(t, 22, i) 328 329 f, err = nsFTwo.FieldFloat("i") 330 assert.NoError(t, err) 331 assert.Equal(t, 23.1, f) 332 } 333 334 func TestConfigRootString(t *testing.T) { 335 spec := NewConfigSpec(). 336 Field(NewStringField("")) 337 338 parsedConfig, err := spec.ParseYAML(`"hello world"`, nil) 339 require.NoError(t, err) 340 341 v, err := parsedConfig.FieldString() 342 require.NoError(t, err) 343 344 assert.Equal(t, "hello world", v) 345 } 346 347 func TestConfigListOfObjects(t *testing.T) { 348 spec := NewConfigSpec(). 349 Field(NewObjectListField("objects", 350 NewStringField("foo"), 351 NewStringField("bar").Default("bar value"), 352 NewIntField("baz"), 353 )) 354 355 _, err := spec.ParseYAML(`objects: 356 - foo: "foo value 1" 357 bar: "bar value 1" 358 `, nil) 359 require.Error(t, err) 360 361 _, err = spec.ParseYAML(`objects: 362 - bar: "bar value 1" 363 baz: 11 364 `, nil) 365 require.Error(t, err) 366 367 _, err = spec.ParseYAML(`objects: []`, nil) 368 require.NoError(t, err) 369 370 parsedConfig, err := spec.ParseYAML(`objects: 371 - foo: "foo value 1" 372 bar: "bar value 1" 373 baz: 11 374 375 - foo: "foo value 2" 376 bar: "bar value 2" 377 baz: 12 378 379 - foo: "foo value 3" 380 baz: 13 381 `, nil) 382 require.NoError(t, err) 383 384 objs, err := parsedConfig.FieldObjectList("objects") 385 require.NoError(t, err) 386 require.Len(t, objs, 3) 387 388 strValue, err := objs[0].FieldString("foo") 389 require.NoError(t, err) 390 assert.Equal(t, "foo value 1", strValue) 391 392 strValue, err = objs[0].FieldString("bar") 393 require.NoError(t, err) 394 assert.Equal(t, "bar value 1", strValue) 395 396 intValue, err := objs[0].FieldInt("baz") 397 require.NoError(t, err) 398 assert.Equal(t, 11, intValue) 399 400 strValue, err = objs[1].FieldString("foo") 401 require.NoError(t, err) 402 assert.Equal(t, "foo value 2", strValue) 403 404 strValue, err = objs[1].FieldString("bar") 405 require.NoError(t, err) 406 assert.Equal(t, "bar value 2", strValue) 407 408 intValue, err = objs[1].FieldInt("baz") 409 require.NoError(t, err) 410 assert.Equal(t, 12, intValue) 411 412 strValue, err = objs[2].FieldString("foo") 413 require.NoError(t, err) 414 assert.Equal(t, "foo value 3", strValue) 415 416 strValue, err = objs[2].FieldString("bar") 417 require.NoError(t, err) 418 assert.Equal(t, "bar value", strValue) 419 420 intValue, err = objs[2].FieldInt("baz") 421 require.NoError(t, err) 422 assert.Equal(t, 13, intValue) 423 } 424 425 func TestConfigTLS(t *testing.T) { 426 spec := NewConfigSpec(). 427 Field(NewTLSField("a")). 428 Field(NewStringField("b")) 429 430 parsedConfig, err := spec.ParseYAML(` 431 a: 432 skip_cert_verify: true 433 b: and this 434 `, nil) 435 require.NoError(t, err) 436 437 _, err = parsedConfig.FieldTLS("b") 438 require.Error(t, err) 439 440 _, err = parsedConfig.FieldTLS("c") 441 require.Error(t, err) 442 443 tConf, err := parsedConfig.FieldTLS("a") 444 require.NoError(t, err) 445 446 assert.True(t, tConf.InsecureSkipVerify) 447 } 448 449 func TestConfigInterpolatedString(t *testing.T) { 450 spec := NewConfigSpec(). 451 Field(NewInterpolatedStringField("a")). 452 Field(NewStringField("b")) 453 454 parsedConfig, err := spec.ParseYAML(` 455 a: foo ${! content() } bar 456 b: this is ${! json } an invalid interp string 457 `, nil) 458 require.NoError(t, err) 459 460 _, err = parsedConfig.FieldInterpolatedString("b") 461 require.Error(t, err) 462 463 _, err = parsedConfig.FieldInterpolatedString("c") 464 require.Error(t, err) 465 466 iConf, err := parsedConfig.FieldInterpolatedString("a") 467 require.NoError(t, err) 468 469 res := iConf.String(NewMessage([]byte("hello world"))) 470 assert.Equal(t, "foo hello world bar", res) 471 }