diff --git a/confmap/provider/yamlprovider/provider_test.go b/confmap/provider/yamlprovider/provider_test.go index 0cf6a49be35..31a9794f7fe 100644 --- a/confmap/provider/yamlprovider/provider_test.go +++ b/confmap/provider/yamlprovider/provider_test.go @@ -92,6 +92,23 @@ func TestMapEntry(t *testing.T) { assert.NoError(t, sp.Shutdown(context.Background())) } +func TestArrayEntry(t *testing.T) { + sp := New() + ret, err := sp.Retrieve(context.Background(), "yaml:service::extensions: [zpages, zpages/foo]", nil) + assert.NoError(t, err) + retMap, err := ret.AsConf() + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{ + "service": map[string]interface{}{ + "extensions": []interface{}{ + "zpages", + "zpages/foo", + }, + }, + }, retMap.ToStringMap()) + assert.NoError(t, sp.Shutdown(context.Background())) +} + func TestNewLine(t *testing.T) { sp := New() ret, err := sp.Retrieve(context.Background(), "yaml:processors::batch/foo::timeout: 3s\nprocessors::batch::timeout: 2s", nil) diff --git a/service/README.md b/service/README.md index dec61dfdc81..64701414de4 100644 --- a/service/README.md +++ b/service/README.md @@ -1,9 +1,9 @@ # OpenTelemetry Collector Service -## How to provide configuration +## How to provide configuration? -The `--config` flag accepts either a file path or values in the form of a config URI `":"`. Currently, the -OpenTelemetry Collector supports the following providers `scheme`: +The `--config` flag accepts either a file path or values in the form of a config URI `":"`. +Currently, the OpenTelemetry Collector supports the following providers `scheme`: - [file](../confmap/provider/fileprovider/provider.go) - Reads configuration from a file. E.g. `file:path/to/config.yaml`. - [env](../confmap/provider/envprovider/provider.go) - Reads configuration from an environment variable. E.g. `env:MY_CONFIG_IN_AN_ENVVAR`. - [yaml](../confmap/provider/yamlprovider/provider.go) - Reads configuration from yaml bytes. E.g. `yaml:exporters::logging::loglevel: debug`. @@ -35,3 +35,63 @@ For more technical details about how configuration is resolved you can read the 2. Merge a `config.yaml` file with the content of a yaml bytes configuration (overwrites the `exporters::logging::loglevel` config) and use the content as the config: `./otelcorecol --config=file:examples/local/otel-config.yaml --config="yaml:exporters::logging::loglevel: info"` + +## How to override config properties? + +The `--set` flag allows to set arbitrary config property. The `--set` values are merged into the final configuration +after all the sources specified by the `--config` are resolved and merged. + +### The Format and Limitations of `--set` + +#### Simple property + +The `--set` option takes always one key/value pair, and it is used like this: `--set key=value`. The YAML equivalent of that is: + +```yaml +key: value +``` + +#### Complex nested keys + +Use dot (`.`) in the pair's name as key separator to reference nested map values. For example, `--set outer.inner=value` is translated into this: + +```yaml +outer: + inner: value +``` + +#### Multiple values + +To set multiple values specify multiple --set flags, so `--set a=b --set c=d` becomes: + +```yaml +a: b +c: d +``` + + +#### Array values + +Arrays can be expressed by enclosing values in `[]`. For example, `--set "key=[a, b, c]"` translates to: + +```yaml +key: + - a + - b + - c +``` + +#### Map values + +Maps can be expressed by enclosing values in `{}`. For example, `"--set "key={a: c}"` translates to: + +```yaml +key: + a: c +``` + +#### Limitations + +1. Does not support setting a key that contains a dot `.`. +2. Does not support setting a key that contains a equal sign `=`. +3. The configuration key separator inside the value part of the property is "::". For example `--set "name={a::b: c}"` is equivalent with `--set name.a.b=c`. \ No newline at end of file diff --git a/service/flags.go b/service/flags.go index 9b638effb19..29b1ae7af3d 100644 --- a/service/flags.go +++ b/service/flags.go @@ -54,8 +54,7 @@ func flags() *flag.FlagSet { flagSet.Func("set", "Set arbitrary component config property. The component has to be defined in the config file and the flag"+ - " has a higher precedence. Array config properties are overridden and maps are joined, note that only a single"+ - " (first) array property can be set e.g. --set=processors.attributes.actions.key=some_key. Example --set=processors.batch.timeout=2s", + " has a higher precedence. Array config properties are overridden and maps are joined. Example --set=processors.batch.timeout=2s", func(s string) error { idx := strings.Index(s, "=") if idx == -1 { diff --git a/service/flags_test.go b/service/flags_test.go index 518f4d33e2d..9661fc342f9 100644 --- a/service/flags_test.go +++ b/service/flags_test.go @@ -29,24 +29,39 @@ func TestSetFlag(t *testing.T) { expectedErr string }{ { - name: "single set", - args: []string{"--set=processors.batch.timeout=2s"}, - expectedConfigs: []string{"yaml:processors::batch::timeout: 2s"}, + name: "simple set", + args: []string{"--set=key=value"}, + expectedConfigs: []string{"yaml:key: value"}, + }, + { + name: "complex nested key", + args: []string{"--set=outer.inner=value"}, + expectedConfigs: []string{"yaml:outer::inner: value"}, + }, + { + name: "set array", + args: []string{"--set=key=[a, b, c]"}, + expectedConfigs: []string{"yaml:key: [a, b, c]"}, + }, + { + name: "set map", + args: []string{"--set=key={a: c}"}, + expectedConfigs: []string{"yaml:key: {a: c}"}, }, { name: "set and config", - args: []string{"--set=processors.batch.timeout=2s", "--config=file:testdata/otelcol-nop.yaml"}, - expectedConfigs: []string{"file:testdata/otelcol-nop.yaml", "yaml:processors::batch::timeout: 2s"}, + args: []string{"--set=key=value", "--config=file:testdata/otelcol-nop.yaml"}, + expectedConfigs: []string{"file:testdata/otelcol-nop.yaml", "yaml:key: value"}, }, { name: "config and set", - args: []string{"--config=file:testdata/otelcol-nop.yaml", "--set=processors.batch.timeout=2s"}, - expectedConfigs: []string{"file:testdata/otelcol-nop.yaml", "yaml:processors::batch::timeout: 2s"}, + args: []string{"--config=file:testdata/otelcol-nop.yaml", "--set=key=value"}, + expectedConfigs: []string{"file:testdata/otelcol-nop.yaml", "yaml:key: value"}, }, { name: "invalid set", - args: []string{"--set=processors.batch.timeout:2s"}, - expectedErr: `invalid value "processors.batch.timeout:2s" for flag -set: missing equal sign`, + args: []string{"--set=key:name"}, + expectedErr: `invalid value "key:name" for flag -set: missing equal sign`, }, }