From 679b9c90446206bab6b20316c69b12701a2e9ed7 Mon Sep 17 00:00:00 2001 From: Gary Brown Date: Thu, 15 Nov 2018 12:27:52 +0000 Subject: [PATCH 1/3] Add support for UI configuration Signed-off-by: Gary Brown --- deploy/examples/all-in-one-with-options.yaml | 11 +++ pkg/apis/io/v1alpha1/freeform.go | 38 ++++++++ pkg/apis/io/v1alpha1/freeform_test.go | 53 +++++++++++ pkg/apis/io/v1alpha1/jaeger_types.go | 6 ++ pkg/apis/io/v1alpha1/zz_generated.deepcopy.go | 39 ++++++++ pkg/configmap/ui.go | 95 +++++++++++++++++++ pkg/configmap/ui_test.go | 73 ++++++++++++++ pkg/controller/jaeger/all-in-one.go | 7 ++ pkg/controller/jaeger/production.go | 7 ++ pkg/deployment/all-in-one.go | 9 +- pkg/deployment/query.go | 9 +- test/e2e/all_in_one_test.go | 94 ++++++++++++++++++ 12 files changed, 437 insertions(+), 4 deletions(-) create mode 100644 pkg/apis/io/v1alpha1/freeform.go create mode 100644 pkg/apis/io/v1alpha1/freeform_test.go create mode 100644 pkg/configmap/ui.go create mode 100644 pkg/configmap/ui_test.go diff --git a/deploy/examples/all-in-one-with-options.yaml b/deploy/examples/all-in-one-with-options.yaml index 9ecb6d738..395803825 100644 --- a/deploy/examples/all-in-one-with-options.yaml +++ b/deploy/examples/all-in-one-with-options.yaml @@ -10,6 +10,17 @@ spec: log-level: debug query: base-path: /jaeger + ui: + options: + dependencies: + menuEnabled: false + tracking: + gaID: UA-000000-2 + menu: + - label: "About Jaeger" + items: + - label: "Documentation" + url: "https://www.jaegertracing.io/docs/latest" storage: options: memory: diff --git a/pkg/apis/io/v1alpha1/freeform.go b/pkg/apis/io/v1alpha1/freeform.go new file mode 100644 index 000000000..56d70237f --- /dev/null +++ b/pkg/apis/io/v1alpha1/freeform.go @@ -0,0 +1,38 @@ +package v1alpha1 + +import ( + "encoding/json" +) + +// FreeForm defines a common options parameter to the different structs +type FreeForm struct { + json []byte +} + +// NewFreeForm build a new FreeForm object based on the given map +func NewFreeForm(o map[string]interface{}) FreeForm { + freeForm := FreeForm{} + if o != nil { + freeForm.json, _ = json.Marshal(o) + } + return freeForm +} + +// UnmarshalJSON implements an alternative parser for this field +func (o *FreeForm) UnmarshalJSON(b []byte) error { + o.json = b + return nil +} + +// MarshalJSON specifies how to convert this object into JSON +func (o FreeForm) MarshalJSON() ([]byte, error) { + if len(o.json) == 0 { + return []byte("{}"), nil + } + return o.json, nil +} + +// IsEmpty determines if the freeform options are empty +func (o FreeForm) IsEmpty() bool { + return len(o.json) == 0 || string(o.json) == "{}" +} diff --git a/pkg/apis/io/v1alpha1/freeform_test.go b/pkg/apis/io/v1alpha1/freeform_test.go new file mode 100644 index 000000000..4ddc64f9e --- /dev/null +++ b/pkg/apis/io/v1alpha1/freeform_test.go @@ -0,0 +1,53 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFreeForm(t *testing.T) { + uiconfig := `{"es":{"password":"changeme","server-urls":"http://elasticsearch:9200","username":"elastic"}}` + o := NewFreeForm(map[string]interface{}{ + "es": map[string]interface{}{ + "server-urls": "http://elasticsearch:9200", + "username": "elastic", + "password": "changeme", + }, + }) + json, err := o.MarshalJSON() + assert.NoError(t, err) + assert.NotNil(t, json) + assert.Equal(t, uiconfig, string(o.json)) +} + +func TestFreeFormUnmarhalMarshal(t *testing.T) { + uiconfig := `{"es":{"password":"changeme","server-urls":"http://elasticsearch:9200","username":"elastic"}}` + o := NewFreeForm(nil) + o.UnmarshalJSON([]byte(uiconfig)) + json, err := o.MarshalJSON() + assert.NoError(t, err) + assert.NotNil(t, json) + assert.Equal(t, uiconfig, string(o.json)) +} + +func TestFreeFormIsEmptyFalse(t *testing.T) { + o := NewFreeForm(map[string]interface{}{ + "es": map[string]interface{}{ + "server-urls": "http://elasticsearch:9200", + "username": "elastic", + "password": "changeme", + }, + }) + assert.False(t, o.IsEmpty()) +} + +func TestFreeFormIsEmptyTrue(t *testing.T) { + o := NewFreeForm(map[string]interface{}{}) + assert.True(t, o.IsEmpty()) +} + +func TestFreeFormIsEmptyNilTrue(t *testing.T) { + o := NewFreeForm(nil) + assert.True(t, o.IsEmpty()) +} diff --git a/pkg/apis/io/v1alpha1/jaeger_types.go b/pkg/apis/io/v1alpha1/jaeger_types.go index cbdf161e8..bf25a8396 100644 --- a/pkg/apis/io/v1alpha1/jaeger_types.go +++ b/pkg/apis/io/v1alpha1/jaeger_types.go @@ -51,6 +51,7 @@ type JaegerSpec struct { Query JaegerQuerySpec `json:"query"` Collector JaegerCollectorSpec `json:"collector"` Agent JaegerAgentSpec `json:"agent"` + UI JaegerUISpec `json:"ui"` Storage JaegerStorageSpec `json:"storage"` Ingress JaegerIngressSpec `json:"ingress"` JaegerCommonSpec @@ -77,6 +78,11 @@ type JaegerQuerySpec struct { JaegerCommonSpec } +// JaegerUISpec defines the options to be used to configure the UI +type JaegerUISpec struct { + Options FreeForm `json:"options"` +} + // JaegerIngressSpec defines the options to be used when deploying the query ingress type JaegerIngressSpec struct { Enabled *bool `json:"enabled"` diff --git a/pkg/apis/io/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/io/v1alpha1/zz_generated.deepcopy.go index 0bd65a409..c623090ab 100644 --- a/pkg/apis/io/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/io/v1alpha1/zz_generated.deepcopy.go @@ -25,6 +25,27 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FreeForm) DeepCopyInto(out *FreeForm) { + *out = *in + if in.json != nil { + in, out := &in.json, &out.json + *out = make([]byte, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FreeForm. +func (in *FreeForm) DeepCopy() *FreeForm { + if in == nil { + return nil + } + out := new(FreeForm) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Jaeger) DeepCopyInto(out *Jaeger) { *out = *in @@ -246,6 +267,7 @@ func (in *JaegerSpec) DeepCopyInto(out *JaegerSpec) { in.Query.DeepCopyInto(&out.Query) in.Collector.DeepCopyInto(&out.Collector) in.Agent.DeepCopyInto(&out.Agent) + in.UI.DeepCopyInto(&out.UI) in.Storage.DeepCopyInto(&out.Storage) in.Ingress.DeepCopyInto(&out.Ingress) in.JaegerCommonSpec.DeepCopyInto(&out.JaegerCommonSpec) @@ -296,6 +318,23 @@ func (in *JaegerStorageSpec) DeepCopy() *JaegerStorageSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerUISpec) DeepCopyInto(out *JaegerUISpec) { + *out = *in + in.Options.DeepCopyInto(&out.Options) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerUISpec. +func (in *JaegerUISpec) DeepCopy() *JaegerUISpec { + if in == nil { + return nil + } + out := new(JaegerUISpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Options) DeepCopyInto(out *Options) { *out = *in diff --git a/pkg/configmap/ui.go b/pkg/configmap/ui.go new file mode 100644 index 000000000..c479b0f4a --- /dev/null +++ b/pkg/configmap/ui.go @@ -0,0 +1,95 @@ +package configmap + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" +) + +// UIConfig represents a UI configmap +type UIConfig struct { + jaeger *v1alpha1.Jaeger +} + +// NewUIConfig builds a new UIConfig struct based on the given spec +func NewUIConfig(jaeger *v1alpha1.Jaeger) *UIConfig { + return &UIConfig{jaeger: jaeger} +} + +// Get returns a configmap specification for the current instance +func (u *UIConfig) Get() *v1.ConfigMap { + // Check for empty map + if u.jaeger.Spec.UI.Options.IsEmpty() { + return nil + } + + json, err := u.jaeger.Spec.UI.Options.MarshalJSON() + if err != nil { + return nil + } + + logrus.Debug("Assembling the UI configmap") + trueVar := true + data := map[string]string{ + "ui": string(json), + } + + return &v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-ui-configuration", u.jaeger.Name), + Namespace: u.jaeger.Namespace, + OwnerReferences: []metav1.OwnerReference{ + metav1.OwnerReference{ + APIVersion: u.jaeger.APIVersion, + Kind: u.jaeger.Kind, + Name: u.jaeger.Name, + UID: u.jaeger.UID, + Controller: &trueVar, + }, + }, + }, + Data: data, + } +} + +// Update will modify the supplied common spec and options to include +// support for the UI configmap if appropriate +func Update(jaeger *v1alpha1.Jaeger, commonSpec *v1alpha1.JaegerCommonSpec, options *[]string) { + // Check for empty map + if jaeger.Spec.UI.Options.IsEmpty() { + return + } + + volume := v1.Volume{ + Name: fmt.Sprintf("%s-ui-configuration-volume", jaeger.Name), + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: fmt.Sprintf("%s-ui-configuration", jaeger.Name), + }, + Items: []v1.KeyToPath{ + v1.KeyToPath{ + Key: "ui", + Path: "ui.json", + }, + }, + }, + }, + } + volumeMount := v1.VolumeMount{ + Name: fmt.Sprintf("%s-ui-configuration-volume", jaeger.Name), + MountPath: "/etc/config", + ReadOnly: true, + } + commonSpec.Volumes = append(commonSpec.Volumes, volume) + commonSpec.VolumeMounts = append(commonSpec.VolumeMounts, volumeMount) + *options = append(*options, "--query.ui-config=/etc/config/ui.json") +} diff --git a/pkg/configmap/ui_test.go b/pkg/configmap/ui_test.go new file mode 100644 index 000000000..e40e76309 --- /dev/null +++ b/pkg/configmap/ui_test.go @@ -0,0 +1,73 @@ +package configmap + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" +) + +func TestNoUIConfig(t *testing.T) { + jaeger := v1alpha1.NewJaeger("TestNoUIConfig") + + config := NewUIConfig(jaeger) + dep := config.Get() + assert.Nil(t, dep) +} + +func TestWithEmptyUIConfig(t *testing.T) { + uiconfig := v1alpha1.NewFreeForm(map[string]interface{}{}) + jaeger := v1alpha1.NewJaeger("TestWithEmptyUIConfig") + jaeger.Spec.UI.Options = uiconfig + + config := NewUIConfig(jaeger) + dep := config.Get() + assert.Nil(t, dep) +} + +func TestWithUIConfig(t *testing.T) { + uiconfig := v1alpha1.NewFreeForm(map[string]interface{}{ + "tracking": map[string]interface{}{ + "gaID": "UA-000000-2", + }, + }) + json := `{"tracking":{"gaID":"UA-000000-2"}}` + jaeger := v1alpha1.NewJaeger("TestWithUIConfig") + jaeger.Spec.UI.Options = uiconfig + + config := NewUIConfig(jaeger) + dep := config.Get() + assert.Equal(t, json, dep.Data["ui"]) +} + +func TestUpdateNoUIConfig(t *testing.T) { + jaeger := v1alpha1.NewJaeger("TestUpdateNoUIConfig") + + commonSpec := v1alpha1.JaegerCommonSpec{} + options := []string{} + + Update(jaeger, &commonSpec, &options) + assert.Len(t, commonSpec.Volumes, 0) + assert.Len(t, commonSpec.VolumeMounts, 0) + assert.Len(t, options, 0) +} + +func TestUpdateWithUIConfig(t *testing.T) { + uiconfig := v1alpha1.NewFreeForm(map[string]interface{}{ + "tracking": map[string]interface{}{ + "gaID": "UA-000000-2", + }, + }) + jaeger := v1alpha1.NewJaeger("TestUpdateWithUIConfig") + jaeger.Spec.UI.Options = uiconfig + + commonSpec := v1alpha1.JaegerCommonSpec{} + options := []string{} + + Update(jaeger, &commonSpec, &options) + assert.Len(t, commonSpec.Volumes, 1) + assert.Len(t, commonSpec.VolumeMounts, 1) + assert.Len(t, options, 1) + assert.Equal(t, "--query.ui-config=/etc/config/ui.json", options[0]) +} diff --git a/pkg/controller/jaeger/all-in-one.go b/pkg/controller/jaeger/all-in-one.go index 1dd4a180d..c8cd11c5c 100644 --- a/pkg/controller/jaeger/all-in-one.go +++ b/pkg/controller/jaeger/all-in-one.go @@ -10,6 +10,7 @@ import ( "github.com/jaegertracing/jaeger-operator/pkg/account" "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/configmap" "github.com/jaegertracing/jaeger-operator/pkg/deployment" "github.com/jaegertracing/jaeger-operator/pkg/ingress" "github.com/jaegertracing/jaeger-operator/pkg/inject" @@ -64,6 +65,12 @@ func (c *allInOneController) Create() []runtime.Object { } } + // add the config map + cm := configmap.NewUIConfig(c.jaeger).Get() + if nil != cm { + os = append(os, cm) + } + return os } diff --git a/pkg/controller/jaeger/production.go b/pkg/controller/jaeger/production.go index 4b6085611..897c0d4d7 100644 --- a/pkg/controller/jaeger/production.go +++ b/pkg/controller/jaeger/production.go @@ -10,6 +10,7 @@ import ( "github.com/jaegertracing/jaeger-operator/pkg/account" "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/configmap" "github.com/jaegertracing/jaeger-operator/pkg/deployment" "github.com/jaegertracing/jaeger-operator/pkg/ingress" "github.com/jaegertracing/jaeger-operator/pkg/inject" @@ -70,6 +71,12 @@ func (c *productionController) Create() []runtime.Object { } } + // add the config map + cm := configmap.NewUIConfig(c.jaeger).Get() + if nil != cm { + os = append(os, cm) + } + return os } diff --git a/pkg/deployment/all-in-one.go b/pkg/deployment/all-in-one.go index fe2ab5412..1a951f160 100644 --- a/pkg/deployment/all-in-one.go +++ b/pkg/deployment/all-in-one.go @@ -11,6 +11,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/configmap" "github.com/jaegertracing/jaeger-operator/pkg/service" "github.com/jaegertracing/jaeger-operator/pkg/storage" "github.com/jaegertracing/jaeger-operator/pkg/util" @@ -46,6 +47,11 @@ func (a *AllInOne) Get() *appsv1.Deployment { commonSpec := util.Merge([]v1alpha1.JaegerCommonSpec{a.jaeger.Spec.AllInOne.JaegerCommonSpec, a.jaeger.Spec.JaegerCommonSpec, baseCommonSpec}) + options := allArgs(a.jaeger.Spec.AllInOne.Options, + a.jaeger.Spec.Storage.Options.Filter(storage.OptionsPrefix(a.jaeger.Spec.Storage.Type))) + + configmap.Update(a.jaeger, commonSpec, &options) + return &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ APIVersion: "apps/v1", @@ -77,8 +83,7 @@ func (a *AllInOne) Get() *appsv1.Deployment { Containers: []v1.Container{{ Image: a.jaeger.Spec.AllInOne.Image, Name: "jaeger", - Args: allArgs(a.jaeger.Spec.AllInOne.Options, - a.jaeger.Spec.Storage.Options.Filter(storage.OptionsPrefix(a.jaeger.Spec.Storage.Type))), + Args: options, Env: []v1.EnvVar{ v1.EnvVar{ Name: "SPAN_STORAGE_TYPE", diff --git a/pkg/deployment/query.go b/pkg/deployment/query.go index 4d974b546..d8b77526a 100644 --- a/pkg/deployment/query.go +++ b/pkg/deployment/query.go @@ -11,6 +11,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/configmap" "github.com/jaegertracing/jaeger-operator/pkg/service" "github.com/jaegertracing/jaeger-operator/pkg/storage" "github.com/jaegertracing/jaeger-operator/pkg/util" @@ -58,6 +59,11 @@ func (q *Query) Get() *appsv1.Deployment { commonSpec := util.Merge([]v1alpha1.JaegerCommonSpec{q.jaeger.Spec.Query.JaegerCommonSpec, q.jaeger.Spec.JaegerCommonSpec, baseCommonSpec}) + options := allArgs(q.jaeger.Spec.Query.Options, + q.jaeger.Spec.Storage.Options.Filter(storage.OptionsPrefix(q.jaeger.Spec.Storage.Type))) + + configmap.Update(q.jaeger, commonSpec, &options) + return &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ APIVersion: "apps/v1", @@ -90,8 +96,7 @@ func (q *Query) Get() *appsv1.Deployment { Containers: []v1.Container{{ Image: q.jaeger.Spec.Query.Image, Name: "jaeger-query", - Args: allArgs(q.jaeger.Spec.Query.Options, - q.jaeger.Spec.Storage.Options.Filter(storage.OptionsPrefix(q.jaeger.Spec.Storage.Type))), + Args: options, Env: []v1.EnvVar{ v1.EnvVar{ Name: "SPAN_STORAGE_TYPE", diff --git a/test/e2e/all_in_one_test.go b/test/e2e/all_in_one_test.go index 52ac34d32..ff177fa1e 100644 --- a/test/e2e/all_in_one_test.go +++ b/test/e2e/all_in_one_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "net/http" + "strings" "testing" "time" @@ -16,6 +17,8 @@ import ( "k8s.io/apimachinery/pkg/util/wait" ) +const TrackingID = "MyTrackingId" + func JaegerAllInOne(t *testing.T) { t.Parallel() ctx := prepare(t) @@ -28,6 +31,10 @@ func JaegerAllInOne(t *testing.T) { if err := allInOneWithUIBasePathTest(t, framework.Global, ctx); err != nil { t.Fatal(err) } + + if err := allInOneWithUIConfigTest(t, framework.Global, ctx); err != nil { + t.Fatal(err) + } } func allInOneTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error { @@ -144,3 +151,90 @@ func allInOneWithUIBasePathTest(t *testing.T, f *framework.Framework, ctx *frame return len(body) > 0, nil }) } + +func allInOneWithUIConfigTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error { + cleanupOptions := &framework.CleanupOptions{TestContext: ctx, Timeout: timeout, RetryInterval: retryInterval} + namespace, err := ctx.GetNamespace() + if err != nil { + return fmt.Errorf("could not get namespace: %v", err) + } + + j := &v1alpha1.Jaeger{ + TypeMeta: metav1.TypeMeta{ + Kind: "Jaeger", + APIVersion: "io.jaegertracing/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "all-in-one-with-ui-config", + Namespace: namespace, + }, + Spec: v1alpha1.JaegerSpec{ + Strategy: "allInOne", + UI: v1alpha1.JaegerUISpec{ + Options: v1alpha1.NewFreeForm(map[string]interface{}{ + "tracking": map[string]interface{}{ + "gaID": TrackingID, + }, + }), + }, + }, + } + + j.Spec.Annotations = map[string]string{ + "nginx.ingress.kubernetes.io/ssl-redirect": "false", + } + + err = f.Client.Create(goctx.TODO(), j, cleanupOptions) + if err != nil { + return err + } + + err = WaitForIngress(t, f.KubeClient, namespace, "all-in-one-with-ui-config-query", retryInterval, timeout) + if err != nil { + return err + } + + i, err := f.KubeClient.ExtensionsV1beta1().Ingresses(namespace).Get("all-in-one-with-ui-config-query", metav1.GetOptions{}) + if err != nil { + return err + } + + if len(i.Status.LoadBalancer.Ingress) != 1 { + return fmt.Errorf("Wrong number of ingresses. Expected 1, was %v", len(i.Status.LoadBalancer.Ingress)) + } + + address := i.Status.LoadBalancer.Ingress[0].IP + url := fmt.Sprintf("http://%s/search", address) + c := http.Client{Timeout: time.Second} + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return err + } + + return wait.Poll(retryInterval, timeout, func() (done bool, err error) { + res, err := c.Do(req) + if err != nil { + return false, err + } + + if res.StatusCode != 200 { + return false, fmt.Errorf("unexpected status code %d", res.StatusCode) + } + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return false, err + } + + if len(body) == 0 { + return false, fmt.Errorf("empty body") + } + + if !strings.Contains(string(body), TrackingID) { + return false, fmt.Errorf("body does not include tracking id: %s", TrackingID) + } + + return true, nil + }) +} From b686e5cff3821f93e7604c94ad556d170030ed58 Mon Sep 17 00:00:00 2001 From: Gary Brown Date: Wed, 21 Nov 2018 10:05:00 +0000 Subject: [PATCH 2/3] Fix e2e test by merging two UI based tests Signed-off-by: Gary Brown --- test/e2e/all_in_one_test.go | 82 ++----------------------------------- 1 file changed, 3 insertions(+), 79 deletions(-) diff --git a/test/e2e/all_in_one_test.go b/test/e2e/all_in_one_test.go index ff177fa1e..c96f9eaff 100644 --- a/test/e2e/all_in_one_test.go +++ b/test/e2e/all_in_one_test.go @@ -28,10 +28,6 @@ func JaegerAllInOne(t *testing.T) { t.Fatal(err) } - if err := allInOneWithUIBasePathTest(t, framework.Global, ctx); err != nil { - t.Fatal(err) - } - if err := allInOneWithUIConfigTest(t, framework.Global, ctx); err != nil { t.Fatal(err) } @@ -73,7 +69,7 @@ func allInOneTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) return e2eutil.WaitForDeployment(t, f.KubeClient, namespace, "my-jaeger", 1, retryInterval, timeout) } -func allInOneWithUIBasePathTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error { +func allInOneWithUIConfigTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error { cleanupOptions := &framework.CleanupOptions{TestContext: ctx, Timeout: timeout, RetryInterval: retryInterval} namespace, err := ctx.GetNamespace() if err != nil { @@ -88,7 +84,7 @@ func allInOneWithUIBasePathTest(t *testing.T, f *framework.Framework, ctx *frame APIVersion: "io.jaegertracing/v1alpha1", }, ObjectMeta: metav1.ObjectMeta{ - Name: "all-in-one-with-base-path", + Name: "all-in-one-with-ui-config", Namespace: namespace, }, Spec: v1alpha1.JaegerSpec{ @@ -98,78 +94,6 @@ func allInOneWithUIBasePathTest(t *testing.T, f *framework.Framework, ctx *frame "query.base-path": basePath, }), }, - }, - } - - j.Spec.Annotations = map[string]string{ - "nginx.ingress.kubernetes.io/ssl-redirect": "false", - } - - err = f.Client.Create(goctx.TODO(), j, cleanupOptions) - if err != nil { - return err - } - - err = WaitForIngress(t, f.KubeClient, namespace, "all-in-one-with-base-path-query", retryInterval, timeout) - if err != nil { - return err - } - - i, err := f.KubeClient.ExtensionsV1beta1().Ingresses(namespace).Get("all-in-one-with-base-path-query", metav1.GetOptions{}) - if err != nil { - return err - } - - if len(i.Status.LoadBalancer.Ingress) != 1 { - return fmt.Errorf("Wrong number of ingresses. Expected 1, was %v", len(i.Status.LoadBalancer.Ingress)) - } - - address := i.Status.LoadBalancer.Ingress[0].IP - url := fmt.Sprintf("http://%s%s/search", address, basePath) - c := http.Client{Timeout: time.Second} - - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return err - } - - return wait.Poll(retryInterval, timeout, func() (done bool, err error) { - res, err := c.Do(req) - if err != nil { - return false, err - } - - if res.StatusCode != 200 { - return false, fmt.Errorf("unexpected status code %d", res.StatusCode) - } - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return false, err - } - - return len(body) > 0, nil - }) -} - -func allInOneWithUIConfigTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error { - cleanupOptions := &framework.CleanupOptions{TestContext: ctx, Timeout: timeout, RetryInterval: retryInterval} - namespace, err := ctx.GetNamespace() - if err != nil { - return fmt.Errorf("could not get namespace: %v", err) - } - - j := &v1alpha1.Jaeger{ - TypeMeta: metav1.TypeMeta{ - Kind: "Jaeger", - APIVersion: "io.jaegertracing/v1alpha1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "all-in-one-with-ui-config", - Namespace: namespace, - }, - Spec: v1alpha1.JaegerSpec{ - Strategy: "allInOne", UI: v1alpha1.JaegerUISpec{ Options: v1alpha1.NewFreeForm(map[string]interface{}{ "tracking": map[string]interface{}{ @@ -204,7 +128,7 @@ func allInOneWithUIConfigTest(t *testing.T, f *framework.Framework, ctx *framewo } address := i.Status.LoadBalancer.Ingress[0].IP - url := fmt.Sprintf("http://%s/search", address) + url := fmt.Sprintf("http://%s%s/search", address, basePath) c := http.Client{Timeout: time.Second} req, err := http.NewRequest(http.MethodGet, url, nil) From b5b97426613ed1f6b89274b2d2bbdcd6a47699d7 Mon Sep 17 00:00:00 2001 From: Gary Brown Date: Wed, 21 Nov 2018 10:37:00 +0000 Subject: [PATCH 3/3] Address the freeform comment and changing the order of adding the configmap in the controllers Signed-off-by: Gary Brown --- pkg/apis/io/v1alpha1/freeform.go | 4 +++- pkg/controller/jaeger/all-in-one.go | 12 ++++++------ pkg/controller/jaeger/production.go | 12 ++++++------ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/pkg/apis/io/v1alpha1/freeform.go b/pkg/apis/io/v1alpha1/freeform.go index 56d70237f..b6757f275 100644 --- a/pkg/apis/io/v1alpha1/freeform.go +++ b/pkg/apis/io/v1alpha1/freeform.go @@ -4,7 +4,9 @@ import ( "encoding/json" ) -// FreeForm defines a common options parameter to the different structs +// FreeForm defines a common options parameter that maintains the hierarchical +// structure of the data, unlike Options which flattens the hierarchy into a +// key/value map where the hierarchy is converted to '.' separated items in the key. type FreeForm struct { json []byte } diff --git a/pkg/controller/jaeger/all-in-one.go b/pkg/controller/jaeger/all-in-one.go index c8cd11c5c..1d7c0b986 100644 --- a/pkg/controller/jaeger/all-in-one.go +++ b/pkg/controller/jaeger/all-in-one.go @@ -41,6 +41,12 @@ func (c *allInOneController) Create() []runtime.Object { os = append(os, acc) } + // add the config map + cm := configmap.NewUIConfig(c.jaeger).Get() + if nil != cm { + os = append(os, cm) + } + // add the deployments os = append(os, inject.OAuthProxy(c.jaeger, dep.Get())) @@ -65,12 +71,6 @@ func (c *allInOneController) Create() []runtime.Object { } } - // add the config map - cm := configmap.NewUIConfig(c.jaeger).Get() - if nil != cm { - os = append(os, cm) - } - return os } diff --git a/pkg/controller/jaeger/production.go b/pkg/controller/jaeger/production.go index 897c0d4d7..0b7d7e5a2 100644 --- a/pkg/controller/jaeger/production.go +++ b/pkg/controller/jaeger/production.go @@ -41,6 +41,12 @@ func (c *productionController) Create() []runtime.Object { os = append(os, acc) } + // add the config map + cm := configmap.NewUIConfig(c.jaeger).Get() + if nil != cm { + os = append(os, cm) + } + // add the deployments os = append(os, collector.Get(), @@ -71,12 +77,6 @@ func (c *productionController) Create() []runtime.Object { } } - // add the config map - cm := configmap.NewUIConfig(c.jaeger).Get() - if nil != cm { - os = append(os, cm) - } - return os }