fix(config): fix codec NPE as parsing format wrongly, fix #2517 (#2518)

* fix[config]: fix codec NPE as parsing format wrongly, fix #2517

* feat: add unit testing for namespace parsing
pull/2543/head
qshuai 2 years ago committed by GitHub
parent c530d63e75
commit a82c82d49f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 36
      contrib/config/apollo/apollo.go
  2. 90
      contrib/config/apollo/apollo_test.go
  3. 2
      contrib/config/apollo/watcher.go

@ -25,6 +25,8 @@ const (
properties = "properties" properties = "properties"
) )
var formats map[string]struct{}
// Option is apollo option // Option is apollo option
type Option func(*options) type Option func(*options)
@ -129,10 +131,16 @@ func NewSource(opts ...Option) config.Source {
func format(ns string) string { func format(ns string) string {
arr := strings.Split(ns, ".") arr := strings.Split(ns, ".")
if len(arr) <= 1 || arr[len(arr)-1] == properties { suffix := arr[len(arr)-1]
if len(arr) <= 1 || suffix == properties {
return json
}
if _, ok := formats[suffix]; !ok {
// fallback
return json return json
} }
return arr[len(arr)-1]
return suffix
} }
func (e *apollo) load() []*config.KeyValue { func (e *apollo) load() []*config.KeyValue {
@ -149,7 +157,7 @@ func (e *apollo) load() []*config.KeyValue {
kvs = append(kvs, kv) kvs = append(kvs, kv)
continue continue
} }
if strings.Contains(ns, ".") && !strings.Contains(ns, properties) && if strings.Contains(ns, ".") && !strings.HasSuffix(ns, "."+properties) &&
(format(ns) == yaml || format(ns) == yml || format(ns) == json) { (format(ns) == yaml || format(ns) == yml || format(ns) == json) {
kv, err := e.getOriginConfig(ns) kv, err := e.getOriginConfig(ns)
if err != nil { if err != nil {
@ -252,16 +260,28 @@ func resolve(key string, value interface{}, target map[string]interface{}) {
// eg: namespace.ext with subKey got namespace.subKey // eg: namespace.ext with subKey got namespace.subKey
func genKey(ns, sub string) string { func genKey(ns, sub string) string {
arr := strings.Split(ns, ".") arr := strings.Split(ns, ".")
if len(arr) < 1 {
return sub
}
if len(arr) == 1 { if len(arr) == 1 {
if ns == "" { if ns == "" {
return sub return sub
} }
return ns + "." + sub return ns + "." + sub
} }
return strings.Join(arr[:len(arr)-1], ".") + "." + sub suffix := arr[len(arr)-1]
_, ok := formats[suffix]
if ok {
return strings.Join(arr[:len(arr)-1], ".") + "." + sub
}
return ns + "." + sub
}
func init() {
formats = make(map[string]struct{})
formats[yaml] = struct{}{}
formats[yml] = struct{}{}
formats[json] = struct{}{}
formats[properties] = struct{}{}
} }

@ -0,0 +1,90 @@
package apollo
import (
"testing"
)
func Test_genKey(t *testing.T) {
type args struct {
ns string
sub string
}
tests := []struct {
name string
args args
want string
}{
{
name: "blank namespace",
args: args{
ns: "",
sub: "x.y",
},
want: "x.y",
},
{
name: "properties namespace",
args: args{
ns: "application",
sub: "x.y",
},
want: "application.x.y",
},
{
name: "namespace with format",
args: args{
ns: "app.yaml",
sub: "x.y",
},
want: "app.x.y",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := genKey(tt.args.ns, tt.args.sub); got != tt.want {
t.Errorf("genKey() = %v, want %v", got, tt.want)
}
})
}
}
func Test_format(t *testing.T) {
tests := []struct {
name string
namespace string
want string
}{
{
name: "properties namespace",
namespace: "application",
want: "json",
},
{
name: "properties namespace #1",
namespace: "app.setting",
want: "json",
},
{
name: "namespace with format[yaml]",
namespace: "app.yaml",
want: "yaml",
},
{
name: "namespace with format[yml]",
namespace: "app.yml",
want: "yml",
},
{
name: "namespace with format[json]",
namespace: "app.json",
want: "json",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := format(tt.namespace); got != tt.want {
t.Errorf("format() = %v, want %v", got, tt.want)
}
})
}
}

@ -25,7 +25,7 @@ type customChangeListener struct {
func (c *customChangeListener) onChange(namespace string, changes map[string]*storage.ConfigChange) []*config.KeyValue { func (c *customChangeListener) onChange(namespace string, changes map[string]*storage.ConfigChange) []*config.KeyValue {
kv := make([]*config.KeyValue, 0, 2) kv := make([]*config.KeyValue, 0, 2)
if strings.Contains(namespace, ".") && !strings.Contains(namespace, properties) && if strings.Contains(namespace, ".") && !strings.HasSuffix(namespace, "."+properties) &&
(format(namespace) == yaml || format(namespace) == yml || format(namespace) == json) { (format(namespace) == yaml || format(namespace) == yml || format(namespace) == json) {
value, err := c.apollo.client.GetConfigCache(namespace).Get("content") value, err := c.apollo.client.GetConfigCache(namespace).Get("content")
if err != nil { if err != nil {

Loading…
Cancel
Save