diff --git a/README.adoc b/README.adoc index 6c61e337b..cb00d9783 100644 --- a/README.adoc +++ b/README.adoc @@ -242,14 +242,13 @@ spec: == Elasticsearch storage -If no `es.server-urls` are provided Jaeger operator creates Elasticsearch CR based on the configuration -provided in storage section. Make sure link:https://github.com/openshift/elasticsearch-operator[elasticsearch-operator] -is running in your cluster otherwise Elasticsearch deployment will not be created. The Elasticsearch is meant -to be dedicated for a single Jaeger instance. +Under some circumstances, the Jaeger Operator can make use of the Elasticsearch operator to provision a suitable Elasticsearch cluster. -At the moment there can be only one Jaeger with Elasticsearch instance in a namespace. +IMPORTANT: this feature is experimental and currently works only on OpenShift clusters. Elasticsearch also requires the memory setting to be configured like `minishift ssh -- 'sudo sysctl -w vm.max_map_count=262144'` -Note that Elasticsearch requires virtual memory settings: `minikube ssh -- 'sudo sysctl -w vm.max_map_count=262144'` +When there are no `es.server-urls` options as part of a Jaeger `production` instance, the Jaeger Operator creates an Elasticsearch cluster via the Elasticsearch Operator by creating a CR based on the configuration provided in storage section. Make sure link:https://github.com/openshift/elasticsearch-operator[elasticsearch-operator] is running in your cluster otherwise the Elasticsearch deployment will not be created. The Elasticsearch cluster is meant to be dedicated for a single Jaeger instance. + +IMPORTANT: At the moment there can be only one Jaeger with self-provisioned Elasticsearch instance per namespace. == Accessing the UI diff --git a/pkg/apis/addtoscheme_io_v1alpha1.go b/pkg/apis/addtoscheme_io_v1alpha1.go index 1208ee274..17fc2628e 100644 --- a/pkg/apis/addtoscheme_io_v1alpha1.go +++ b/pkg/apis/addtoscheme_io_v1alpha1.go @@ -2,9 +2,10 @@ package apis import ( "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" ) func init() { // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back - AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme, esv1alpha1.SchemeBuilder.AddToScheme) } diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 55687b9c1..cc03cc1c6 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -2,10 +2,7 @@ package controller import ( routev1 "github.com/openshift/api/route/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/manager" - - esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" ) // AddToManagerFuncs is a list of functions to add all Controllers to the Manager @@ -16,9 +13,6 @@ func AddToManager(m manager.Manager) error { if err := routev1.AddToScheme(m.GetScheme()); err != nil { return err } - // TODO temporal fix https://github.com/jaegertracing/jaeger-operator/issues/206 - gv := schema.GroupVersion{Group: "logging.openshift.io", Version: "v1alpha1"} - m.GetScheme().AddKnownTypes(gv, &esv1alpha1.Elasticsearch{}) for _, f := range AddToManagerFuncs { if err := f(m); err != nil { diff --git a/pkg/controller/jaeger/elasticsearch.go b/pkg/controller/jaeger/elasticsearch.go new file mode 100644 index 000000000..d7d717393 --- /dev/null +++ b/pkg/controller/jaeger/elasticsearch.go @@ -0,0 +1,52 @@ +package jaeger + +import ( + "context" + + log "github.com/sirupsen/logrus" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/inventory" + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" +) + +func (r *ReconcileJaeger) applyElasticsearches(jaeger v1alpha1.Jaeger, desired []esv1alpha1.Elasticsearch) error { + opts := client.MatchingLabels(map[string]string{ + "app.kubernetes.io/instance": jaeger.Name, + "app.kubernetes.io/managed-by": "jaeger-operator", + }) + list := &esv1alpha1.ElasticsearchList{} + if err := r.client.List(context.Background(), opts, list); err != nil { + return err + } + + logFields := log.WithFields(log.Fields{ + "namespace": jaeger.Namespace, + "instance": jaeger.Name, + }) + + inv := inventory.ForElasticsearches(list.Items, desired) + for _, d := range inv.Create { + logFields.WithField("elasticsearch", d.Name).Debug("creating elasticsearch") + if err := r.client.Create(context.Background(), &d); err != nil { + return err + } + } + + for _, d := range inv.Update { + logFields.WithField("elasticsearch", d.Name).Debug("updating elasticsearch") + if err := r.client.Update(context.Background(), &d); err != nil { + return err + } + } + + for _, d := range inv.Delete { + logFields.WithField("elasticsearch", d.Name).Debug("deleting elasticsearch") + if err := r.client.Delete(context.Background(), &d); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/controller/jaeger/elasticsearch_test.go b/pkg/controller/jaeger/elasticsearch_test.go new file mode 100644 index 000000000..6f07441da --- /dev/null +++ b/pkg/controller/jaeger/elasticsearch_test.go @@ -0,0 +1,131 @@ +package jaeger + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" + "github.com/jaegertracing/jaeger-operator/pkg/strategy" +) + +func TestElasticsearchesCreate(t *testing.T) { + // prepare + nsn := types.NamespacedName{ + Name: "TestElasticsearchesCreate", + } + + objs := []runtime.Object{ + v1alpha1.NewJaeger(nsn.Name), + } + + req := reconcile.Request{ + NamespacedName: nsn, + } + + r, cl := getReconciler(objs) + r.strategyChooser = func(jaeger *v1alpha1.Jaeger) strategy.S { + s := strategy.New().WithElasticsearches([]esv1alpha1.Elasticsearch{{ + ObjectMeta: metav1.ObjectMeta{ + Name: nsn.Name, + }, + }}) + return s + } + + // test + res, err := r.Reconcile(req) + + // verify + assert.NoError(t, err) + assert.False(t, res.Requeue, "We don't requeue for now") + + persisted := &esv1alpha1.Elasticsearch{} + persistedName := types.NamespacedName{ + Name: nsn.Name, + Namespace: nsn.Namespace, + } + err = cl.Get(context.Background(), persistedName, persisted) + assert.Equal(t, persistedName.Name, persisted.Name) + assert.NoError(t, err) +} + +func TestElasticsearchesUpdate(t *testing.T) { + // prepare + nsn := types.NamespacedName{ + Name: "TestElasticsearchesUpdate", + } + + orig := esv1alpha1.Elasticsearch{} + orig.Name = nsn.Name + orig.Annotations = map[string]string{"key": "value"} + + objs := []runtime.Object{ + v1alpha1.NewJaeger(nsn.Name), + &orig, + } + + r, cl := getReconciler(objs) + r.strategyChooser = func(jaeger *v1alpha1.Jaeger) strategy.S { + updated := esv1alpha1.Elasticsearch{} + updated.Name = orig.Name + updated.Annotations = map[string]string{"key": "new-value"} + + s := strategy.New().WithElasticsearches([]esv1alpha1.Elasticsearch{updated}) + return s + } + + // test + _, err := r.Reconcile(reconcile.Request{NamespacedName: nsn}) + assert.NoError(t, err) + + // verify + persisted := &esv1alpha1.Elasticsearch{} + persistedName := types.NamespacedName{ + Name: orig.Name, + Namespace: orig.Namespace, + } + err = cl.Get(context.Background(), persistedName, persisted) + assert.Equal(t, "new-value", persisted.Annotations["key"]) + assert.NoError(t, err) +} + +func TestElasticsearchesDelete(t *testing.T) { + // prepare + nsn := types.NamespacedName{ + Name: "TestElasticsearchesDelete", + } + + orig := esv1alpha1.Elasticsearch{} + orig.Name = nsn.Name + + objs := []runtime.Object{ + v1alpha1.NewJaeger(nsn.Name), + &orig, + } + + r, cl := getReconciler(objs) + r.strategyChooser = func(jaeger *v1alpha1.Jaeger) strategy.S { + return strategy.S{} + } + + // test + _, err := r.Reconcile(reconcile.Request{NamespacedName: nsn}) + assert.NoError(t, err) + + // verify + persisted := &esv1alpha1.Elasticsearch{} + persistedName := types.NamespacedName{ + Name: orig.Name, + Namespace: orig.Namespace, + } + err = cl.Get(context.Background(), persistedName, persisted) + assert.Empty(t, persisted.Name) + assert.Error(t, err) // not found +} diff --git a/pkg/controller/jaeger/jaeger_controller.go b/pkg/controller/jaeger/jaeger_controller.go index d5ce8146a..3313dc3df 100644 --- a/pkg/controller/jaeger/jaeger_controller.go +++ b/pkg/controller/jaeger/jaeger_controller.go @@ -132,6 +132,10 @@ func defaultStrategyChooser(instance *v1alpha1.Jaeger) strategy.S { } func (r *ReconcileJaeger) apply(jaeger v1alpha1.Jaeger, str strategy.S) error { + if err := r.applyElasticsearches(jaeger, str.Elasticsearches()); err != nil { + return err + } + if err := r.applyRoles(jaeger, str.Roles()); err != nil { return err } diff --git a/pkg/controller/jaeger/jaeger_controller_test.go b/pkg/controller/jaeger/jaeger_controller_test.go index aa98e9b91..623bf8e37 100644 --- a/pkg/controller/jaeger/jaeger_controller_test.go +++ b/pkg/controller/jaeger/jaeger_controller_test.go @@ -14,6 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1" + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" "github.com/jaegertracing/jaeger-operator/pkg/strategy" ) @@ -90,8 +91,16 @@ func TestDeletedInstance(t *testing.T) { func getReconciler(objs []runtime.Object) (*ReconcileJaeger, client.Client) { s := scheme.Scheme + + // OpenShift Route osv1.Install(s) + + // Jaeger s.AddKnownTypes(v1alpha1.SchemeGroupVersion, &v1alpha1.Jaeger{}) + + // Jaeger's Elasticsearch + s.AddKnownTypes(v1alpha1.SchemeGroupVersion, &esv1alpha1.Elasticsearch{}, &esv1alpha1.ElasticsearchList{}) + cl := fake.NewFakeClient(objs...) return &ReconcileJaeger{client: cl, scheme: s}, cl } diff --git a/pkg/inventory/elasticsearch.go b/pkg/inventory/elasticsearch.go new file mode 100644 index 000000000..a24d1e08a --- /dev/null +++ b/pkg/inventory/elasticsearch.go @@ -0,0 +1,62 @@ +package inventory + +import ( + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" +) + +// Elasticsearch represents the elastic search inventory based on the current and desired states +type Elasticsearch struct { + Create []esv1alpha1.Elasticsearch + Update []esv1alpha1.Elasticsearch + Delete []esv1alpha1.Elasticsearch +} + +// ForElasticsearches builds a new elastic search inventory based on the existing and desired states +func ForElasticsearches(existing []esv1alpha1.Elasticsearch, desired []esv1alpha1.Elasticsearch) Elasticsearch { + update := []esv1alpha1.Elasticsearch{} + mcreate := esMap(desired) + mdelete := esMap(existing) + + for k, v := range mcreate { + if t, ok := mdelete[k]; ok { + tp := t.DeepCopy() + + tp.Spec = v.Spec + tp.ObjectMeta.OwnerReferences = v.ObjectMeta.OwnerReferences + + for k, v := range v.ObjectMeta.Annotations { + tp.ObjectMeta.Annotations[k] = v + } + + for k, v := range v.ObjectMeta.Labels { + tp.ObjectMeta.Labels[k] = v + } + + update = append(update, *tp) + delete(mcreate, k) + delete(mdelete, k) + } + } + + return Elasticsearch{ + Create: esList(mcreate), + Update: update, + Delete: esList(mdelete), + } +} + +func esMap(deps []esv1alpha1.Elasticsearch) map[string]esv1alpha1.Elasticsearch { + m := map[string]esv1alpha1.Elasticsearch{} + for _, d := range deps { + m[d.Name] = d + } + return m +} + +func esList(m map[string]esv1alpha1.Elasticsearch) []esv1alpha1.Elasticsearch { + l := []esv1alpha1.Elasticsearch{} + for _, v := range m { + l = append(l, v) + } + return l +} diff --git a/pkg/inventory/elasticsearch_test.go b/pkg/inventory/elasticsearch_test.go new file mode 100644 index 000000000..529520407 --- /dev/null +++ b/pkg/inventory/elasticsearch_test.go @@ -0,0 +1,53 @@ +package inventory + +import ( + "testing" + + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" +) + +func TestElasticsearchInventory(t *testing.T) { + toCreate := esv1alpha1.Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Name: "to-create", + }, + } + toUpdate := esv1alpha1.Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Name: "to-update", + }, + Spec: esv1alpha1.ElasticsearchSpec{ + ManagementState: esv1alpha1.ManagementStateManaged, + }, + } + updated := esv1alpha1.Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Name: "to-update", + }, + Spec: esv1alpha1.ElasticsearchSpec{ + ManagementState: esv1alpha1.ManagementStateUnmanaged, + }, + } + toDelete := esv1alpha1.Elasticsearch{ + ObjectMeta: metav1.ObjectMeta{ + Name: "to-delete", + }, + } + + existing := []esv1alpha1.Elasticsearch{toUpdate, toDelete} + desired := []esv1alpha1.Elasticsearch{updated, toCreate} + + inv := ForElasticsearches(existing, desired) + assert.Len(t, inv.Create, 1) + assert.Equal(t, "to-create", inv.Create[0].Name) + + assert.Len(t, inv.Update, 1) + assert.Equal(t, "to-update", inv.Update[0].Name) + assert.Equal(t, esv1alpha1.ManagementStateUnmanaged, inv.Update[0].Spec.ManagementState) + + assert.Len(t, inv.Delete, 1) + assert.Equal(t, "to-delete", inv.Delete[0].Name) +} diff --git a/pkg/storage/elasticsearch.go b/pkg/storage/elasticsearch.go index 169897942..fc034c5ed 100644 --- a/pkg/storage/elasticsearch.go +++ b/pkg/storage/elasticsearch.go @@ -19,9 +19,10 @@ const ( caPath = volumeMountPath + "/ca" keyPath = volumeMountPath + "/key" certPath = volumeMountPath + "/cert" - elasticsearchUrl = "https://elasticsearch:9200" + elasticsearchURL = "https://elasticsearch:9200" ) +// ShouldDeployElasticsearch determines whether a new instance of Elasticsearch should be deployed func ShouldDeployElasticsearch(s v1alpha1.JaegerStorageSpec) bool { if !strings.EqualFold(s.Type, "elasticsearch") { return false @@ -30,10 +31,12 @@ func ShouldDeployElasticsearch(s v1alpha1.JaegerStorageSpec) bool { return !ok } +// ElasticsearchDeployment represents an ES deployment for Jaeger type ElasticsearchDeployment struct { Jaeger *v1alpha1.Jaeger } +// InjectStorageConfiguration changes the given spec to include ES-related command line options func (ed *ElasticsearchDeployment) InjectStorageConfiguration(p *v1.PodSpec) { p.Volumes = append(p.Volumes, v1.Volume{ Name: volumeName, @@ -47,7 +50,7 @@ func (ed *ElasticsearchDeployment) InjectStorageConfiguration(p *v1.PodSpec) { if len(p.Containers) > 0 { // TODO add to archive storage if it is enabled? p.Containers[0].Args = append(p.Containers[0].Args, - "--es.server-urls="+elasticsearchUrl, + "--es.server-urls="+elasticsearchURL, "--es.token-file="+k8sTokenFile, "--es.tls.ca="+caPath) if !containsPrefix("--es.num-shards", p.Containers[0].Args) { @@ -67,6 +70,7 @@ func (ed *ElasticsearchDeployment) InjectStorageConfiguration(p *v1.PodSpec) { } } +// InjectIndexCleanerConfiguration changes the given spec to include the options for the index cleaner func (ed *ElasticsearchDeployment) InjectIndexCleanerConfiguration(p *v1.PodSpec) { p.Volumes = append(p.Volumes, v1.Volume{ Name: volumeName, @@ -79,7 +83,7 @@ func (ed *ElasticsearchDeployment) InjectIndexCleanerConfiguration(p *v1.PodSpec // we assume jaeger containers are first if len(p.Containers) > 0 { // the size of arguments array should be always 2 - p.Containers[0].Args[1] = elasticsearchUrl + p.Containers[0].Args[1] = elasticsearchURL p.Containers[0].Env = append(p.Containers[0].Env, v1.EnvVar{Name: "ES_TLS", Value: "true"}, v1.EnvVar{Name: "ES_TLS_CA", Value: caPath}, @@ -94,11 +98,20 @@ func (ed *ElasticsearchDeployment) InjectIndexCleanerConfiguration(p *v1.PodSpec } } -func (ed *ElasticsearchDeployment) createCr() *esv1alpha1.Elasticsearch { +// Elasticsearch returns an ES CR for the deployment +func (ed *ElasticsearchDeployment) Elasticsearch() *esv1alpha1.Elasticsearch { return &esv1alpha1.Elasticsearch{ ObjectMeta: metav1.ObjectMeta{ - Namespace: ed.Jaeger.Namespace, - Name: esSecret.name, + Namespace: ed.Jaeger.Namespace, + Name: esSecret.name, + Labels: map[string]string{ + "app": "jaeger", + "app.kubernetes.io/name": esSecret.name, + "app.kubernetes.io/instance": ed.Jaeger.Name, + "app.kubernetes.io/component": "elasticsearch", + "app.kubernetes.io/part-of": "jaeger", + "app.kubernetes.io/managed-by": "jaeger-operator", + }, OwnerReferences: []metav1.OwnerReference{asOwner(ed.Jaeger)}, }, Spec: esv1alpha1.ElasticsearchSpec{ diff --git a/pkg/storage/elasticsearch/v1alpha1/register.go b/pkg/storage/elasticsearch/v1alpha1/register.go new file mode 100644 index 000000000..f2a021b1d --- /dev/null +++ b/pkg/storage/elasticsearch/v1alpha1/register.go @@ -0,0 +1,14 @@ +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "logging.openshift.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/pkg/storage/elasticsearch/v1alpha1/types.go b/pkg/storage/elasticsearch/v1alpha1/types.go index b8fb683fd..26abea185 100644 --- a/pkg/storage/elasticsearch/v1alpha1/types.go +++ b/pkg/storage/elasticsearch/v1alpha1/types.go @@ -204,3 +204,7 @@ const ( UpdateClusterSettings ClusterEvent = "UpdateClusterSettings" NoEvent ClusterEvent = "NoEvent" ) + +func init() { + SchemeBuilder.Register(&Elasticsearch{}, &ElasticsearchList{}) +} diff --git a/pkg/storage/elasticsearch_test.go b/pkg/storage/elasticsearch_test.go index 9bcf8e52f..df2674e40 100644 --- a/pkg/storage/elasticsearch_test.go +++ b/pkg/storage/elasticsearch_test.go @@ -84,7 +84,7 @@ func TestCreateElasticsearchCR(t *testing.T) { j.Namespace = "myproject" j.Spec.Storage.Elasticsearch = test.jEsSpec es := &ElasticsearchDeployment{Jaeger: j} - cr := es.createCr() + cr := es.Elasticsearch() assert.Equal(t, "myproject", cr.Namespace) assert.Equal(t, "elasticsearch", cr.Name) trueVar := true @@ -108,7 +108,7 @@ func TestInject(t *testing.T) { Containers: []v1.Container{{ Args: []string{ "foo", - "--es.server-urls=" + elasticsearchUrl, + "--es.server-urls=" + elasticsearchURL, "--es.token-file=" + k8sTokenFile, "--es.tls.ca=" + caPath, "--es.num-shards=0", @@ -133,7 +133,7 @@ func TestInject(t *testing.T) { Containers: []v1.Container{{ Args: []string{ "--es.num-shards=15", - "--es.server-urls=" + elasticsearchUrl, + "--es.server-urls=" + elasticsearchURL, "--es.token-file=" + k8sTokenFile, "--es.tls.ca=" + caPath, "--es.num-replicas=1", diff --git a/pkg/strategy/production.go b/pkg/strategy/production.go index 6a9a22ae5..dd32b1a51 100644 --- a/pkg/strategy/production.go +++ b/pkg/strategy/production.go @@ -42,12 +42,6 @@ func newProductionStrategy(jaeger *v1alpha1.Jaeger) S { c.configMaps = append(c.configMaps, *cm) } - cDep := collector.Get() - queryDep := inject.OAuthProxy(jaeger, query.Get()) - - // add the deployments - c.deployments = []appsv1.Deployment{*collector.Get(), *inject.OAuthProxy(jaeger, query.Get())} - // add the daemonsets if ds := agent.Get(); ds != nil { c.daemonSets = []appsv1.DaemonSet{*ds} @@ -85,12 +79,16 @@ func newProductionStrategy(jaeger *v1alpha1.Jaeger) S { if isBoolTrue(jaeger.Spec.Storage.EsIndexCleaner.Enabled) { if strings.EqualFold(jaeger.Spec.Storage.Type, "elasticsearch") { indexCleaner = cronjob.CreateEsIndexCleaner(jaeger) - c.cronJobs = append(c.cronJobs, *indexCleaner) } else { logrus.WithField("type", jaeger.Spec.Storage.Type).Warn("Skipping Elasticsearch index cleaner job due to unsupported storage.") } } + // prepare the deployments, which may get changed by the elasticsearch routine + cDep := collector.Get() + queryDep := inject.OAuthProxy(jaeger, query.Get()) + + // assembles the pieces for an elasticsearch self-provisioned deployment via the elasticsearch operator if storage.ShouldDeployElasticsearch(jaeger.Spec.Storage) { es := &storage.ElasticsearchDeployment{ Jaeger: jaeger, @@ -109,6 +107,7 @@ func newProductionStrategy(jaeger *v1alpha1.Jaeger) S { queryDep.Spec.Template.Spec.ServiceAccountName, ), ) + c.elasticsearches = append(c.elasticsearches, *es.Elasticsearch()) es.InjectStorageConfiguration(&queryDep.Spec.Template.Spec) es.InjectStorageConfiguration(&cDep.Spec.Template.Spec) @@ -118,5 +117,13 @@ func newProductionStrategy(jaeger *v1alpha1.Jaeger) S { } } + // the index cleaner ES job, which may have been changed by the ES self-provisioning routine + if indexCleaner != nil { + c.cronJobs = append(c.cronJobs, *indexCleaner) + } + + // add the deployments, which may have been changed by the ES self-provisioning routine + c.deployments = []appsv1.Deployment{*cDep, *queryDep} + return c } diff --git a/pkg/strategy/strategy.go b/pkg/strategy/strategy.go index 7100fffd8..d5b8559c2 100644 --- a/pkg/strategy/strategy.go +++ b/pkg/strategy/strategy.go @@ -8,23 +8,26 @@ import ( "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" rbacv1 "k8s.io/api/rbac/v1" + + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" ) // S knows what type of deployments to build based on a given spec type S struct { - typ Type - accounts []v1.ServiceAccount - configMaps []v1.ConfigMap - cronJobs []batchv1beta1.CronJob - daemonSets []appsv1.DaemonSet - dependencies []batchv1.Job - deployments []appsv1.Deployment - ingresses []v1beta1.Ingress - routes []osv1.Route - roles []rbacv1.Role - roleBindings []rbacv1.RoleBinding - services []v1.Service - secrets []v1.Secret + typ Type + accounts []v1.ServiceAccount + configMaps []v1.ConfigMap + cronJobs []batchv1beta1.CronJob + daemonSets []appsv1.DaemonSet + dependencies []batchv1.Job + deployments []appsv1.Deployment + elasticsearches []esv1alpha1.Elasticsearch + ingresses []v1beta1.Ingress + routes []osv1.Route + roles []rbacv1.Role + roleBindings []rbacv1.RoleBinding + services []v1.Service + secrets []v1.Secret } // Type represents a specific deployment strategy, like 'all-in-one' @@ -88,6 +91,12 @@ func (s S) WithDependencies(deps []batchv1.Job) S { return s } +// WithElasticsearches returns the strategy with the given list of elastic search instances +func (s S) WithElasticsearches(es []esv1alpha1.Elasticsearch) S { + s.elasticsearches = es + return s +} + // WithIngresses returns the strategy with the given list of dependencies func (s S) WithIngresses(i []v1beta1.Ingress) S { s.ingresses = i @@ -149,6 +158,11 @@ func (s S) Deployments() []appsv1.Deployment { return s.deployments } +// Elasticsearches returns the list of elastic search instances for this strategy +func (s S) Elasticsearches() []esv1alpha1.Elasticsearch { + return s.elasticsearches +} + // Ingresses returns the list of ingress objects for this strategy. This might be platform-dependent func (s S) Ingresses() []v1beta1.Ingress { return s.ingresses diff --git a/pkg/strategy/strategy_test.go b/pkg/strategy/strategy_test.go index c1d2b4263..a6dbd7ece 100644 --- a/pkg/strategy/strategy_test.go +++ b/pkg/strategy/strategy_test.go @@ -10,6 +10,8 @@ import ( batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" + + esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1" ) func TestWithAccounts(t *testing.T) { @@ -42,6 +44,11 @@ func TestWithDeployments(t *testing.T) { assert.Len(t, c.Deployments(), 1) } +func TestWithElasticsearches(t *testing.T) { + c := New().WithElasticsearches([]esv1alpha1.Elasticsearch{{}}) + assert.Len(t, c.Elasticsearches(), 1) +} + func TestWithIngresses(t *testing.T) { c := New().WithIngresses([]v1beta1.Ingress{{}}) assert.Len(t, c.Ingresses(), 1)