Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only configure Stack Monitoring if association reconciled #5339

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions pkg/controller/common/stackmon/monitoring/monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ type HasMonitoring interface {
MonitoringAssociation(ref commonv1.ObjectSelector) commonv1.Association
}

// IsReconcilable return true if a resource has at least one association defined in its specification
// and all defined associations are configured.
func IsReconcilable(resource HasMonitoring) bool {
if !IsDefined(resource) {
return false
}
allRefs := append(resource.GetMonitoringMetricsRefs(), resource.GetMonitoringLogsRefs()...)
for _, ref := range allRefs {
if !resource.MonitoringAssociation(ref).AssociationConf().IsConfigured() {
return false
}
}
return true
}

// IsDefined return true if a resource has at least one association for Stack Monitoring defined in its specification
// (can be one for logs or one for metrics).
func IsDefined(resource HasMonitoring) bool {
return IsMetricsDefined(resource) || IsLogsDefined(resource)
}
Expand Down
151 changes: 151 additions & 0 deletions pkg/controller/common/stackmon/monitoring/monitoring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/types"

commonv1 "github.com/elastic/cloud-on-k8s/pkg/apis/common/v1"
esv1 "github.com/elastic/cloud-on-k8s/pkg/apis/elasticsearch/v1"
Expand All @@ -27,6 +28,156 @@ var (
}
)

func TestIsReconcilable(t *testing.T) {
tests := []struct {
name string
es esv1.Elasticsearch
want bool
}{
{
name: "without monitoring",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Version: "7.13.1",
},
},
want: false,
},
{
name: "with metrics monitoring defined but not configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
},
},
},
want: false,
},
{
name: "with metrics monitoring defined and configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://es.xyz", AuthSecretName: "-"},
},
},
want: true,
},
{
name: "with logs monitoring defined and configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Logs: esv1.LogsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://es.xyz", AuthSecretName: "-"},
},
},
want: true,
},
{
name: "with metrics and logs monitoring defined and partially configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
Logs: esv1.LogsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m2", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://es.xyz", AuthSecretName: "-"},
},
},
want: false,
},
{
name: "with metrics and logs monitoring defined and partially configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
Logs: esv1.LogsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m2", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://es.xyz", AuthSecretName: "-"},
},
},
want: false,
},
{
name: "with logs and metrics monitoring defined and configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
Logs: esv1.LogsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://m1.xyz", AuthSecretName: "-"},
},
},
want: true,
},
{
name: "with distinct logs and metrics monitoring defined and configured",
es: esv1.Elasticsearch{
Spec: esv1.ElasticsearchSpec{
Monitoring: esv1.Monitoring{
Metrics: esv1.MetricsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m1", Namespace: "b"}},
},
Logs: esv1.LogsMonitoring{
ElasticsearchRefs: []commonv1.ObjectSelector{{Name: "m2", Namespace: "b"}},
},
},
},
AssocConfs: map[types.NamespacedName]commonv1.AssociationConf{
types.NamespacedName{Name: "m1", Namespace: "b"}: {URL: "https://m1.xyz", AuthSecretName: "-"},
types.NamespacedName{Name: "m2", Namespace: "b"}: {URL: "https://m2.xyz", AuthSecretName: "-"},
},
},
want: true,
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := IsReconcilable(&tc.es)
if got != tc.want {
t.Errorf("IsReconcilable() got = %v, want %v", got, tc.want)
return
}
})
}
}

func TestIsDefined(t *testing.T) {
assert.False(t, IsDefined(&sampleEs))
assert.True(t, IsDefined(&sampleMonitoredEs))
Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/elasticsearch/stackmon/beat_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ var (

// ReconcileConfigSecrets reconciles the secrets holding beats configuration
func ReconcileConfigSecrets(client k8s.Client, es esv1.Elasticsearch) error {
if !monitoring.IsReconcilable(&es) {
return nil
}

if monitoring.IsMetricsDefined(&es) {
b, err := Metricbeat(client, es)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions pkg/controller/elasticsearch/stackmon/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ func Filebeat(client k8s.Client, es esv1.Elasticsearch) (stackmon.BeatSidecar, e
// WithMonitoring updates the Elasticsearch Pod template builder to deploy Metricbeat and Filebeat in sidecar containers
// in the Elasticsearch pod and injects the volumes for the beat configurations and the ES CA certificates.
func WithMonitoring(client k8s.Client, builder *defaults.PodTemplateBuilder, es esv1.Elasticsearch) (*defaults.PodTemplateBuilder, error) {
// no monitoring defined, skip
if !monitoring.IsDefined(&es) {
if !monitoring.IsReconcilable(&es) {
return builder, nil
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/kibana/stackmon/beat_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ var (

// ReconcileConfigSecrets reconciles the secrets holding beats configuration
func ReconcileConfigSecrets(client k8s.Client, kb kbv1.Kibana) error {
if !monitoring.IsReconcilable(&kb) {
return nil
}

if monitoring.IsMetricsDefined(&kb) {
b, err := Metricbeat(client, kb)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions pkg/controller/kibana/stackmon/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ func Filebeat(client k8s.Client, kb kbv1.Kibana) (stackmon.BeatSidecar, error) {
// WithMonitoring updates the Kibana Pod template builder to deploy Metricbeat and Filebeat in sidecar containers
// in the Kibana pod and injects the volumes for the beat configurations and the ES CA certificates.
func WithMonitoring(client k8s.Client, builder *defaults.PodTemplateBuilder, kb kbv1.Kibana) (*defaults.PodTemplateBuilder, error) {
// no monitoring defined, skip
if !monitoring.IsDefined(&kb) {
if !monitoring.IsReconcilable(&kb) {
return builder, nil
}

Expand Down