diff --git a/pkg/apis/jaegertracing/v1/freeform.go b/pkg/apis/jaegertracing/v1/freeform.go index c8de4b50b..98ac1a057 100644 --- a/pkg/apis/jaegertracing/v1/freeform.go +++ b/pkg/apis/jaegertracing/v1/freeform.go @@ -39,3 +39,12 @@ func (o FreeForm) MarshalJSON() ([]byte, error) { func (o FreeForm) IsEmpty() bool { return len(o.json) == 0 || string(o.json) == "{}" } + +// GetMap returns a map created from json +func (o FreeForm) GetMap() (map[string]interface{}, error) { + m := map[string]interface{}{} + if err := json.Unmarshal(o.json, &m); err != nil { + return nil, err + } + return m, nil +} diff --git a/pkg/apis/jaegertracing/v1/freeform_test.go b/pkg/apis/jaegertracing/v1/freeform_test.go index 33328bb6d..a64d67a1a 100644 --- a/pkg/apis/jaegertracing/v1/freeform_test.go +++ b/pkg/apis/jaegertracing/v1/freeform_test.go @@ -51,3 +51,25 @@ func TestFreeFormIsEmptyNilTrue(t *testing.T) { o := NewFreeForm(nil) assert.True(t, o.IsEmpty()) } + +func TestToMap(t *testing.T) { + tests := []struct { + m map[string]interface{} + expected map[string]interface{} + err string + }{ + {err: "unexpected end of JSON input"}, + {m: map[string]interface{}{"foo": "bar$"}, expected: map[string]interface{}{"foo": "bar$"}}, + {m: map[string]interface{}{"foo": true}, expected: map[string]interface{}{"foo": true}}, + } + for _, test := range tests { + f := NewFreeForm(test.m) + got, err := f.GetMap() + if test.err != "" { + assert.EqualError(t, err, test.err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, got) + } + } +} diff --git a/pkg/strategy/controller.go b/pkg/strategy/controller.go index 99868f27d..ab238de5a 100644 --- a/pkg/strategy/controller.go +++ b/pkg/strategy/controller.go @@ -82,6 +82,7 @@ func normalize(jaeger *v1.Jaeger) { normalizeIndexCleaner(&jaeger.Spec.Storage.EsIndexCleaner, jaeger.Spec.Storage.Type) normalizeElasticsearch(&jaeger.Spec.Storage.Elasticsearch) normalizeRollover(&jaeger.Spec.Storage.Rollover) + normalizeUI(&jaeger.Spec) } func normalizeSparkDependencies(spec *v1.JaegerDependenciesSpec, storage string) { @@ -133,6 +134,27 @@ func normalizeRollover(spec *v1.JaegerEsRolloverSpec) { } } +func normalizeUI(spec *v1.JaegerSpec) { + sOpts := spec.Storage.Options.Map() + uiOpts := map[string]interface{}{} + if !spec.UI.Options.IsEmpty() { + if m, err := spec.UI.Options.GetMap(); err == nil { + uiOpts = m + } + } + // we respect explicit UI config + if _, ok := uiOpts["archiveEnabled"]; ok { + return + } + if strings.EqualFold(sOpts["es-archive.enabled"], "true") || + strings.EqualFold(sOpts["cassandra-archive.enabled"], "true") { + uiOpts["archiveEnabled"] = true + } + if len(uiOpts) > 0 { + spec.UI.Options = v1.NewFreeForm(uiOpts) + } +} + func unknownStorage(typ string) bool { for _, k := range storage.ValidTypes() { if strings.EqualFold(typ, k) { diff --git a/pkg/strategy/controller_test.go b/pkg/strategy/controller_test.go index 779ae80fa..4ab20e8e2 100644 --- a/pkg/strategy/controller_test.go +++ b/pkg/strategy/controller_test.go @@ -239,6 +239,48 @@ func TestNormalizeElasticsearch(t *testing.T) { } } +func TestNormalizeUI(t *testing.T) { + tests := []struct { + j *v1.JaegerSpec + expected *v1.JaegerSpec + }{ + { + j: &v1.JaegerSpec{}, + expected: &v1.JaegerSpec{}, + }, + { + j: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es.archive.enabled": "false"})}}, + expected: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es.archive.enabled": "false"})}}, + }, + { + j: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}}, + expected: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"archiveEnabled": true})}}, + }, + { + j: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"cassandra-archive.enabled": "true"})}}, + expected: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"cassandra-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"archiveEnabled": true})}}, + }, + { + j: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"other": "foo"})}}, + expected: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"other": "foo", "archiveEnabled": true})}}, + }, + { + j: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"archiveEnabled": "respectThis"})}}, + expected: &v1.JaegerSpec{Storage: v1.JaegerStorageSpec{Options: v1.NewOptions(map[string]interface{}{"es-archive.enabled": "true"})}, + UI: v1.JaegerUISpec{Options: v1.NewFreeForm(map[string]interface{}{"archiveEnabled": "respectThis"})}}, + }, + } + for _, test := range tests { + normalizeUI(test.j) + assert.Equal(t, test.expected, test.j) + } +} + func assertHasAllObjects(t *testing.T, name string, s S, deployments map[string]bool, daemonsets map[string]bool, services map[string]bool, ingresses map[string]bool, routes map[string]bool, serviceAccounts map[string]bool, configMaps map[string]bool) { for _, o := range s.Deployments() { deployments[o.Name] = true