diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 6d3746b9a45..e6009606fba 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -47,6 +47,9 @@ https://github.com/elastic/beats/compare/v5.0.0-alpha5...master[Check the HEAD d - Fix Elasticsearch structured error response parsing error. {issue}2229[2229] - Fixed the run script to allow the overriding of the configuration file. {issue}2171[2171] - Fix logstash output crash if no hosts are configured. {issue}2325[2325] +- Fix array value support in -E CLI flag. {pull}2521[2521] +- Fix merging array values if -c CLI flag is used multiple times. {pull}2521[2521] +- Fix beats failing to start due to invalid duplicate key error in configuration file. {pull}2521[2521] *Metricbeat* - Fix module filters to work properly with drop_event filter. {issue}2249[2249] diff --git a/glide.yaml b/glide.yaml index 9e068072522..706cdcb5574 100644 --- a/glide.yaml +++ b/glide.yaml @@ -75,7 +75,7 @@ import: - package: github.com/dustin/go-humanize version: 499693e27ee0d14ffab67c31ad065fdb3d34ea75 - package: github.com/elastic/go-ucfg - version: v0.3.4 + version: v0.3.6 - package: github.com/armon/go-socks5 version: 3a873e99f5400ad7706e464e905ffcc94b3ff247 - package: github.com/pkg/errors diff --git a/vendor/github.com/elastic/go-ucfg/CHANGELOG.md b/vendor/github.com/elastic/go-ucfg/CHANGELOG.md index a4a376866d5..d7e45eb422e 100644 --- a/vendor/github.com/elastic/go-ucfg/CHANGELOG.md +++ b/vendor/github.com/elastic/go-ucfg/CHANGELOG.md @@ -14,6 +14,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +## [0.3.6] + +### Fixed +- Fix duplicate key error when normalizing tables. #63 + +## [0.3.5] + +### Fixed +- Fix merging array values. #59 +- Fix initializing empty array values. #58 + ## [0.3.4] ### Fixed @@ -100,7 +111,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Introduced CHANGELOG.md for documenting changes to ucfg. -[Unreleased]: https://github.com/elastic/go-ucfg/compare/v0.3.4...HEAD +[Unreleased]: https://github.com/elastic/go-ucfg/compare/v0.3.6...HEAD +[0.3.6]: https://github.com/elastic/go-ucfg/compare/v0.3.5...v0.3.6 +[0.3.5]: https://github.com/elastic/go-ucfg/compare/v0.3.4...v0.3.5 [0.3.4]: https://github.com/elastic/go-ucfg/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/elastic/go-ucfg/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/elastic/go-ucfg/compare/v0.3.1...v0.3.2 diff --git a/vendor/github.com/elastic/go-ucfg/README.md b/vendor/github.com/elastic/go-ucfg/README.md index 16f110abcb8..7a5c962820a 100644 --- a/vendor/github.com/elastic/go-ucfg/README.md +++ b/vendor/github.com/elastic/go-ucfg/README.md @@ -81,4 +81,4 @@ The above uses `Counter` as the config variable. ucfg assures that the value is ucfg has the following requirements: -* Golang 1.6 +* Golang 1.5+ diff --git a/vendor/github.com/elastic/go-ucfg/merge.go b/vendor/github.com/elastic/go-ucfg/merge.go index f3085c8a9dc..b1851c78202 100644 --- a/vendor/github.com/elastic/go-ucfg/merge.go +++ b/vendor/github.com/elastic/go-ucfg/merge.go @@ -10,6 +10,7 @@ import ( func (c *Config) Merge(from interface{}, options ...Option) error { opts := makeOptions(options) other, err := normalize(opts, from) + if err != nil { return err } @@ -17,6 +18,13 @@ func (c *Config) Merge(from interface{}, options ...Option) error { } func mergeConfig(opts *options, to, from *Config) Error { + if err := mergeConfigDict(opts, to, from); err != nil { + return err + } + return mergeConfigArr(opts, to, from) +} + +func mergeConfigDict(opts *options, to, from *Config) Error { for k, v := range from.fields.dict() { ctx := context{ parent: cfgSub{to}, @@ -48,6 +56,56 @@ func mergeConfig(opts *options, to, from *Config) Error { return nil } +func mergeConfigArr(opts *options, to, from *Config) Error { + l := len(to.fields.array()) + if l > len(from.fields.array()) { + l = len(from.fields.array()) + } + + // merge array indexes available in to and from + for i := 0; i < l; i++ { + ctx := context{ + parent: cfgSub{to}, + field: fmt.Sprintf("%v", i), + } + + v := from.fields.array()[i] + + old := to.fields.array()[i] + subOld, err := old.toConfig(opts) + if err != nil { + to.fields.setAt(i, cfgSub{to}, v.cpy(ctx)) + continue + } + + subFrom, err := v.toConfig(opts) + if err != nil { + to.fields.setAt(i, cfgSub{to}, v.cpy(ctx)) + } + + if err := mergeConfig(opts, subOld, subFrom); err != nil { + return err + } + } + + end := len(from.fields.array()) + if end <= l { + return nil + } + + // add additional array entries not yet in 'to' + for ; l < end; l++ { + ctx := context{ + parent: cfgSub{to}, + field: fmt.Sprintf("%v", l), + } + v := from.fields.array()[l] + to.fields.setAt(l, cfgSub{to}, v.cpy(ctx)) + } + + return nil +} + // convert from into normalized *Config checking for errors // before merging generated(normalized) config with current config func normalize(opts *options, from interface{}) (*Config, Error) { @@ -166,14 +224,19 @@ func normalizeSetField( } old = nil } - if old != nil { - if _, isNil := val.(*cfgNil); val == nil || isNil { - return nil - } + + switch { + case !isNil(old) && isNil(val): + return nil + case isNil(old): + return p.SetValue(cfg, opts, val) + case isSub(old) && isSub(val): + cfgOld, _ := old.toConfig(opts) + cfgVal, _ := val.toConfig(opts) + return mergeConfig(opts, cfgOld, cfgVal) + default: return raiseDuplicateKey(cfg, name) } - - return p.SetValue(cfg, opts, val) } func normalizeStructValue(opts *options, ctx context, from reflect.Value) (value, Error) { diff --git a/vendor/github.com/elastic/go-ucfg/path.go b/vendor/github.com/elastic/go-ucfg/path.go index 2efc606a85d..0e0e85d3a88 100644 --- a/vendor/github.com/elastic/go-ucfg/path.go +++ b/vendor/github.com/elastic/go-ucfg/path.go @@ -45,23 +45,25 @@ func parsePath(in, sep string) cfgPath { if sep == "" { return cfgPath{ sep: sep, - fields: []field{namedField{in}}, + fields: []field{parseField(in)}, } } elems := strings.Split(in, sep) fields := make([]field, 0, len(elems)) for _, elem := range elems { - if idx, err := strconv.ParseInt(elem, 0, 64); err == nil { - fields = append(fields, idxField{int(idx)}) - } else { - fields = append(fields, namedField{elem}) - } + fields = append(fields, parseField(elem)) } - return cfgPath{fields: fields, sep: sep} } +func parseField(in string) field { + if idx, err := strconv.ParseInt(in, 0, 64); err == nil { + return idxField{int(idx)} + } + return namedField{in} +} + func (p cfgPath) String() string { if len(p.fields) == 0 { return "" @@ -159,7 +161,7 @@ func (p cfgPath) SetValue(cfg *Config, opt *options, val value) Error { return err } - if _, isNil := v.(*cfgNil); v == nil || isNil { + if isNil(v) { break } node = v @@ -200,7 +202,7 @@ func (i idxField) SetValue(opts *options, elem value, v value) Error { return raiseExpectedObject(opts, elem) } - sub.c.fields.setAt(i.i, v) + sub.c.fields.setAt(i.i, elem, v) v.SetContext(context{parent: elem, field: i.String()}) return nil } diff --git a/vendor/github.com/elastic/go-ucfg/reify.go b/vendor/github.com/elastic/go-ucfg/reify.go index 755bb3dad07..bc2fc2aeca2 100644 --- a/vendor/github.com/elastic/go-ucfg/reify.go +++ b/vendor/github.com/elastic/go-ucfg/reify.go @@ -170,7 +170,7 @@ func reifyGetField( value = nil } - if _, ok := value.(*cfgNil); value == nil || ok { + if isNil(value) { if err := runValidators(nil, opts.validators); err != nil { return raiseValidation(cfg.ctx, cfg.metadata, name, err) } @@ -430,7 +430,7 @@ func reifyPrimitive( t, baseType reflect.Type, ) (reflect.Value, Error) { // zero initialize value if val==nil - if _, ok := val.(*cfgNil); ok { + if isNil(val) { return pointerize(t, baseType, reflect.Zero(baseType)), nil } diff --git a/vendor/github.com/elastic/go-ucfg/types.go b/vendor/github.com/elastic/go-ucfg/types.go index 230262f4afc..4df7621554d 100644 --- a/vendor/github.com/elastic/go-ucfg/types.go +++ b/vendor/github.com/elastic/go-ucfg/types.go @@ -297,7 +297,7 @@ func (c cfgSub) cpy(ctx context) value { for i, f := range arr { ctx := f.Context() v := f.cpy(context{field: ctx.field, parent: newC}) - fields.setAt(i, v) + fields.setAt(i, newC, v) } } @@ -503,3 +503,19 @@ func (s *cfgSplice) toFloat(opt *options) (float64, error) { } return strconv.ParseFloat(str, 64) } + +func isNil(v value) bool { + if v == nil { + return true + } + _, tst := v.(*cfgNil) + return tst +} + +func isSub(v value) bool { + if v == nil { + return false + } + _, tst := v.(cfgSub) + return tst +} diff --git a/vendor/github.com/elastic/go-ucfg/ucfg.go b/vendor/github.com/elastic/go-ucfg/ucfg.go index 9e44d4beaf6..9972f20f91b 100644 --- a/vendor/github.com/elastic/go-ucfg/ucfg.go +++ b/vendor/github.com/elastic/go-ucfg/ucfg.go @@ -1,6 +1,7 @@ package ucfg import ( + "fmt" "reflect" "regexp" "time" @@ -138,11 +139,19 @@ func (f *fields) add(v value) { f.a = append(f.a, v) } -func (f *fields) setAt(idx int, v value) { - if idx >= len(f.a) { +func (f *fields) setAt(idx int, parent, v value) { + l := len(f.a) + if idx >= l { tmp := make([]value, idx+1) copy(tmp, f.a) + + for i := l; i < idx; i++ { + ctx := context{parent: parent, field: fmt.Sprintf("%d", i)} + tmp[i] = &cfgNil{cfgPrimitive{ctx, nil}} + } + f.a = tmp } + f.a[idx] = v }