Skip to content

Commit

Permalink
operator: Add namespace and tenantId labels to RecordingRules (#9971)
Browse files Browse the repository at this point in the history
Co-authored-by: Periklis Tsirakidis <periklis@redhat.com>
  • Loading branch information
Mohamed-Amine Bouqsimi and periklis committed Jul 19, 2023
1 parent 6d2b3e8 commit d4f364b
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 1 deletion.
1 change: 1 addition & 0 deletions operator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Main

- [9971](https://github.com/grafana/loki/pull/9971) **aminesnow**: Add namespace and tenantId labels to RecordingRules
- [9906](https://github.com/grafana/loki/pull/9906) **JoaoBraveCoding**: Add mTLS authentication to tenants
- [9963](https://github.com/grafana/loki/pull/9963) **xperimental**: Fix application tenant alertmanager configuration
- [9795](https://github.com/grafana/loki/pull/9795) **JoaoBraveCoding**: Add initContainer to zone aware components to gatekeep them from starting without the AZ annotation
Expand Down
7 changes: 7 additions & 0 deletions operator/apis/loki/v1/recordingrule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ type RecordingRuleGroupSpec struct {
// +kubebuilder:validation:Required
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="LogQL Expression"
Expr string `json:"expr"`

// Labels to add to each recording rule.
//
// +optional
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Labels"
Labels map[string]string `json:"labels,omitempty"`
}

// RecordingRuleStatus defines the observed state of RecordingRule
Expand Down
9 changes: 8 additions & 1 deletion operator/apis/loki/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,9 @@ spec:
alerts.
displayName: LogQL Expression
path: groups[0].rules[0].expr
- description: Labels to add to each recording rule.
displayName: Labels
path: groups[0].rules[0].labels
- description: The name of the time series to output to. Must be a valid metric
name.
displayName: Metric Name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ spec:
cycle this is evaluated at the current time, and all
resultant time series become pending/firing alerts.
type: string
labels:
additionalProperties:
type: string
description: Labels to add to each recording rule.
type: object
record:
description: The name of the time series to output to.
Must be a valid metric name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ spec:
cycle this is evaluated at the current time, and all
resultant time series become pending/firing alerts.
type: string
labels:
additionalProperties:
type: string
description: Labels to add to each recording rule.
type: object
record:
description: The name of the time series to output to.
Must be a valid metric name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,9 @@ spec:
alerts.
displayName: LogQL Expression
path: groups[0].rules[0].expr
- description: Labels to add to each recording rule.
displayName: Labels
path: groups[0].rules[0].labels
- description: The name of the time series to output to. Must be a valid metric
name.
displayName: Metric Name
Expand Down
10 changes: 10 additions & 0 deletions operator/internal/manifests/internal/rules/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ func MarshalRecordingRule(a lokiv1.RecordingRule) (string, error) {
Groups: aa.Spec.Groups,
}

for _, group := range ar.Groups {
for _, rule := range group.Rules {
if rule.Labels == nil {
rule.Labels = map[string]string{}
}

rule.Labels[tenantLabel] = aa.Spec.TenantID
}
}

content, err := yaml.Marshal(ar)
if err != nil {
return "", kverrors.Wrap(err, "failed to marshal recording rule", "name", aa.Name, "namespace", aa.Namespace)
Expand Down
13 changes: 13 additions & 0 deletions operator/internal/manifests/internal/rules/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
lokiv1 "github.com/grafana/loki/operator/apis/loki/v1"
"github.com/grafana/loki/operator/internal/manifests/internal/rules"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestMarshalAlertingRule(t *testing.T) {
Expand Down Expand Up @@ -109,15 +110,24 @@ groups:
rate({container="nginx"}[1m])
)
record: nginx:requests:rate1m
labels:
tenantId: a-tenant
environment: test
- expr: |-
sum(
rate({container="banana"}[5m])
)
record: banana:requests:rate5m
labels:
tenantId: a-tenant
`

r := lokiv1.RecordingRule{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test-ns",
},
Spec: lokiv1.RecordingRuleSpec{
TenantID: "a-tenant",
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "a-recording",
Expand All @@ -129,6 +139,9 @@ groups:
rate({container="nginx"}[1m])
)`,
Record: "nginx:requests:rate1m",
Labels: map[string]string{
"environment": "test",
},
},
{
Expr: `sum(
Expand Down
195 changes: 195 additions & 0 deletions operator/internal/manifests/openshift/recordingrule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package openshift

import (
"testing"

lokiv1 "github.com/grafana/loki/operator/apis/loki/v1"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestRecordingRuleTenantLabels(t *testing.T) {
tt := []struct {
rule *lokiv1.RecordingRule
want *lokiv1.RecordingRule
}{
{
rule: &lokiv1.RecordingRule{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test-ns",
},
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantApplication,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
want: &lokiv1.RecordingRule{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test-ns",
},
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantApplication,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
Labels: map[string]string{
opaDefaultLabelMatcher: "test-ns",
},
},
},
},
},
},
},
},
{
rule: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantInfrastructure,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
want: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantInfrastructure,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
},
{
rule: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantAudit,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
want: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantAudit,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
},
{
rule: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantNetwork,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
want: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: tenantNetwork,
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
},
{
rule: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: "unknown",
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
want: &lokiv1.RecordingRule{
Spec: lokiv1.RecordingRuleSpec{
TenantID: "unknown",
Groups: []*lokiv1.RecordingRuleGroup{
{
Name: "test-group",
Rules: []*lokiv1.RecordingRuleGroupSpec{
{
Record: "record",
},
},
},
},
},
},
},
}
for _, tc := range tt {
tc := tc
t.Run(tc.rule.Spec.TenantID, func(t *testing.T) {
t.Parallel()
RecordingRuleTenantLabels(tc.rule)

require.Equal(t, tc.want, tc.rule)
})
}
}
27 changes: 27 additions & 0 deletions operator/internal/manifests/openshift/recordngrule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package openshift

import lokiv1 "github.com/grafana/loki/operator/apis/loki/v1"

func RecordingRuleTenantLabels(r *lokiv1.RecordingRule) {
switch r.Spec.TenantID {
case tenantApplication:
for groupIdx, group := range r.Spec.Groups {
group := group
for ruleIdx, rule := range group.Rules {
rule := rule
if rule.Labels == nil {
rule.Labels = map[string]string{}
}
rule.Labels[opaDefaultLabelMatcher] = r.Namespace
group.Rules[ruleIdx] = rule
}
r.Spec.Groups[groupIdx] = group
}
case tenantInfrastructure, tenantAudit:
// Do nothing
case tenantNetwork:
// Do nothing
default:
// Do nothing
}
}
16 changes: 16 additions & 0 deletions operator/internal/manifests/rules_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func RulesConfigMapShards(opts *Options) ([]*corev1.ConfigMap, error) {
}

for _, r := range opts.RecordingRules {
r := r
if opts.Stack.Tenants != nil {
configureRecordingRuleForMode(&r, opts.Stack.Tenants.Mode)
}

c, err := rules.MarshalRecordingRule(r)
if err != nil {
return nil, err
Expand Down Expand Up @@ -91,3 +96,14 @@ func configureAlertingRuleForMode(ar *lokiv1.AlertingRule, mode lokiv1.ModeType)
// Do nothing
}
}

func configureRecordingRuleForMode(r *lokiv1.RecordingRule, mode lokiv1.ModeType) {
switch mode {
case lokiv1.Static, lokiv1.Dynamic:
// Do nothing
case lokiv1.OpenshiftLogging:
openshift.RecordingRuleTenantLabels(r)
case lokiv1.OpenshiftNetwork:
// Do nothing
}
}

0 comments on commit d4f364b

Please sign in to comment.