Skip to content

Commit

Permalink
reconcile prometheus ServiceMonitor resources
Browse files Browse the repository at this point in the history
Signed-off-by: Ashley Schuett <[email protected]>
  • Loading branch information
ashleyschuett committed May 1, 2021
1 parent a8da67d commit 9c1a718
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 36 deletions.
4 changes: 2 additions & 2 deletions pkg/virt-operator/kubevirt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,11 @@ var _ = Describe("KubeVirt Operator", func() {
// test OpenShift components
stores.IsOnOpenshift = true

informers.ServiceMonitor, serviceMonitorSource = testutils.NewFakeInformerFor(&promv1.ServiceMonitor{})
informers.ServiceMonitor, serviceMonitorSource = testutils.NewFakeInformerFor(&promv1.ServiceMonitor{Spec: promv1.ServiceMonitorSpec{}})
stores.ServiceMonitorCache = informers.ServiceMonitor.GetStore()
stores.ServiceMonitorEnabled = true

informers.PrometheusRule, prometheusRuleSource = testutils.NewFakeInformerFor(&promv1.PrometheusRule{})
informers.PrometheusRule, prometheusRuleSource = testutils.NewFakeInformerFor(&promv1.PrometheusRule{Spec: promv1.PrometheusRuleSpec{}})
stores.PrometheusRuleCache = informers.PrometheusRule.GetStore()
stores.PrometheusRulesEnabled = true

Expand Down
1 change: 1 addition & 0 deletions pkg/virt-operator/resource/apply/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ go_library(
"//vendor/github.com/blang/semver:go_default_library",
"//vendor/github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/github.com/imdario/mergo:go_default_library",
"//vendor/github.com/openshift/api/operator/v1:go_default_library",
"//vendor/github.com/openshift/api/security/v1:go_default_library",
"//vendor/github.com/openshift/library-go/pkg/operator/resource/resourcemerge:go_default_library",
Expand Down
104 changes: 70 additions & 34 deletions pkg/virt-operator/resource/apply/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"fmt"

promv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/imdario/mergo"
"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

Expand All @@ -17,56 +20,89 @@ func (r *Reconciler) createOrUpdateServiceMonitors() error {
return nil
}

var err error
for _, serviceMonitor := range r.targetStrategy.ServiceMonitors() {
err = r.createOrUpdateServiceMonitor(serviceMonitor.DeepCopy())
if err != nil {
return err
}
}

return nil
}

func (r *Reconciler) createOrUpdateServiceMonitor(serviceMonitor *promv1.ServiceMonitor) error {
prometheusClient := r.clientset.PrometheusClient()
version, imageRegistry, id := getTargetVersionRegistryID(r.kv)

for _, serviceMonitor := range r.targetStrategy.ServiceMonitors() {
var cachedServiceMonitor *promv1.ServiceMonitor
var cachedServiceMonitor *promv1.ServiceMonitor

serviceMonitor := serviceMonitor.DeepCopy()
obj, exists, _ := r.stores.ServiceMonitorCache.Get(serviceMonitor)
if exists {
cachedServiceMonitor = obj.(*promv1.ServiceMonitor)
}
obj, exists, _ := r.stores.ServiceMonitorCache.Get(serviceMonitor)
if exists {
cachedServiceMonitor = obj.(*promv1.ServiceMonitor)
}

injectOperatorMetadata(r.kv, &serviceMonitor.ObjectMeta, version, imageRegistry, id, true)
if !exists {
// Create non existent
r.expectations.ServiceMonitor.RaiseExpectations(r.kvKey, 1, 0)
_, err := prometheusClient.MonitoringV1().ServiceMonitors(serviceMonitor.Namespace).Create(context.Background(), serviceMonitor, metav1.CreateOptions{})
if err != nil {
r.expectations.ServiceMonitor.LowerExpectations(r.kvKey, 1, 0)
return fmt.Errorf("unable to create serviceMonitor %+v: %v", serviceMonitor, err)
}
injectOperatorMetadata(r.kv, &serviceMonitor.ObjectMeta, version, imageRegistry, id, true)
if !exists {
// Create non existent
r.expectations.ServiceMonitor.RaiseExpectations(r.kvKey, 1, 0)
_, err := prometheusClient.MonitoringV1().ServiceMonitors(serviceMonitor.Namespace).Create(context.Background(), serviceMonitor, metav1.CreateOptions{})
if err != nil {
r.expectations.ServiceMonitor.LowerExpectations(r.kvKey, 1, 0)
return fmt.Errorf("unable to create serviceMonitor %+v: %v", serviceMonitor, err)
}

log.Log.V(2).Infof("serviceMonitor %v created", serviceMonitor.GetName())
log.Log.V(2).Infof("serviceMonitor %v created", serviceMonitor.GetName())
return nil
}

} else if !objectMatchesVersion(&cachedServiceMonitor.ObjectMeta, version, imageRegistry, id, r.kv.GetGeneration()) {
newSpec, err := json.Marshal(serviceMonitor.Spec)
if err != nil {
return err
}
endpointsModified, err := ensureServiceMonitorSpec(serviceMonitor, cachedServiceMonitor)
if err != nil {
return err
}

ops, err := getPatchWithObjectMetaAndSpec([]string{}, &serviceMonitor.ObjectMeta, newSpec)
if err != nil {
return err
}
modified := resourcemerge.BoolPtr(false)
resourcemerge.EnsureObjectMeta(modified, &cachedServiceMonitor.ObjectMeta, serviceMonitor.ObjectMeta)

_, err = prometheusClient.MonitoringV1().ServiceMonitors(serviceMonitor.Namespace).Patch(context.Background(), serviceMonitor.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("unable to patch serviceMonitor %+v: %v", serviceMonitor, err)
}
// there was no change to metadata and the spec fields are equal
if !*modified && !endpointsModified {
log.Log.V(2).Infof("serviceMonitor %v is up-to-date", serviceMonitor.GetName())
return nil
}

log.Log.V(2).Infof("serviceMonitor %v updated", serviceMonitor.GetName())
// Add Spec Patch
newSpec, err := json.Marshal(serviceMonitor.Spec)
if err != nil {
return err
}

ops, err := getPatchWithObjectMetaAndSpec([]string{}, &serviceMonitor.ObjectMeta, newSpec)
if err != nil {
return err
}

} else {
log.Log.V(4).Infof("serviceMonitor %v is up-to-date", serviceMonitor.GetName())
}
_, err = prometheusClient.MonitoringV1().ServiceMonitors(serviceMonitor.Namespace).Patch(context.Background(), serviceMonitor.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
if err != nil {
return fmt.Errorf("unable to patch serviceMonitor %+v: %v", serviceMonitor, err)
}

log.Log.V(2).Infof("serviceMonitor %v updated", serviceMonitor.GetName())

return nil
}

func ensureServiceMonitorSpec(required, existing *promv1.ServiceMonitor) (bool, error) {
if err := mergo.Merge(&existing.Spec, &required.Spec); err != nil {
return false, err
}

if equality.Semantic.DeepEqual(existing.Spec, required.Spec) {
return false, nil
}

return true, nil
}

func (r *Reconciler) createOrUpdatePrometheusRules() error {

if !r.stores.PrometheusRulesEnabled {
Expand Down

0 comments on commit 9c1a718

Please sign in to comment.