From 21a7f96b636f9f7764f2653598782bd049b91e35 Mon Sep 17 00:00:00 2001 From: Periklis Tsirakidis Date: Tue, 28 Nov 2023 13:29:45 +0100 Subject: [PATCH] operator: Add support for blocking queries per tenant (#11094) Co-authored-by: Robert Jacob --- operator/CHANGELOG.md | 3 +- operator/apis/loki/v1/lokistack_types.go | 93 +++++++- .../apis/loki/v1/zz_generated.deepcopy.go | 94 +++++++- operator/apis/loki/v1beta1/lokistack_types.go | 14 +- .../loki-operator.clusterserviceversion.yaml | 23 +- .../loki.grafana.com_lokistacks.yaml | 37 +++ .../loki-operator.clusterserviceversion.yaml | 23 +- .../loki.grafana.com_lokistacks.yaml | 37 +++ .../loki-operator.clusterserviceversion.yaml | 23 +- .../loki.grafana.com_lokistacks.yaml | 37 +++ .../bases/loki.grafana.com_lokistacks.yaml | 37 +++ .../loki-operator.clusterserviceversion.yaml | 21 ++ .../loki-operator.clusterserviceversion.yaml | 21 ++ .../loki-operator.clusterserviceversion.yaml | 21 ++ operator/docs/operator/api.md | 215 +++++++++++++++++- operator/internal/manifests/config_test.go | 32 +-- .../manifests/internal/config/build.go | 12 +- .../manifests/internal/config/build_test.go | 105 +++++++-- .../internal/config/loki-runtime-config.yaml | 18 ++ .../manifests/internal/config/options.go | 2 +- operator/internal/manifests/options_test.go | 42 ++-- operator/internal/metrics/metrics.go | 2 +- 22 files changed, 840 insertions(+), 72 deletions(-) diff --git a/operator/CHANGELOG.md b/operator/CHANGELOG.md index 8b415c1229f7e..2f0b018ac5ff4 100644 --- a/operator/CHANGELOG.md +++ b/operator/CHANGELOG.md @@ -1,12 +1,13 @@ ## Main +- [11094](https://github.com/grafana/loki/pull/11094) **periklis**: Add support for blocking queries per tenant - [11288](https://github.com/grafana/loki/pull/11288) **periklis**: Fix custom CA for object-store in ruler component - [11091](https://github.com/grafana/loki/pull/11091) **periklis**: Add automatic stream sharding support - [11022](https://github.com/grafana/loki/pull/11022) **JoaoBraveCoding**: Remove outdated BoltDB dashboards - [10932](https://github.com/grafana/loki/pull/10932) **JoaoBraveCoding**: Adds new value v13 to schema - [11232](https://github.com/grafana/loki/pull/11232) **periklis**: Update dependencies and dev tools - [11129](https://github.com/grafana/loki/pull/11129) **periklis**: Update deps to secure webhooks for CVE-2023-44487 -- + ## 0.5.0 (2023-10-24) - [10924](https://github.com/grafana/loki/pull/10924) **periklis**: Update Loki operand to v2.9.2 diff --git a/operator/apis/loki/v1/lokistack_types.go b/operator/apis/loki/v1/lokistack_types.go index 29e09887b3dfc..8b163ff780300 100644 --- a/operator/apis/loki/v1/lokistack_types.go +++ b/operator/apis/loki/v1/lokistack_types.go @@ -1,6 +1,8 @@ package v1 import ( + "strings" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -633,6 +635,65 @@ type QueryLimitSpec struct { CardinalityLimit int32 `json:"cardinalityLimit,omitempty"` } +// BlockedQueryType defines which type of query a blocked query should apply to. +// +// +kubebuilder:validation:Enum=filter;limited;metric +type BlockedQueryType string + +const ( + // BlockedQueryFilter is used, when the blocked query should apply to queries using a log filter. + BlockedQueryFilter BlockedQueryType = "filter" + // BlockedQueryLimited is used, when the blocked query should apply to queries without a filter or a metric aggregation. + BlockedQueryLimited BlockedQueryType = "limited" + // BlockedQueryMetric is used, when the blocked query should apply to queries with an aggregation. + BlockedQueryMetric BlockedQueryType = "metric" +) + +// BlockedQueryTypes defines a slice of BlockedQueryType values to be used for a blocked query. +type BlockedQueryTypes []BlockedQueryType + +// BlockedQuerySpec defines the rule spec for queries to be blocked. +// +// +kubebuilder:validation:MinProperties:=1 +type BlockedQuerySpec struct { + // Hash is a 32-bit FNV-1 hash of the query string. + // + // +optional + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:number",displayName="Query Hash" + Hash int32 `json:"hash,omitempty"` + // Pattern defines the pattern matching the queries to be blocked. + // + // +optional + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Query Pattern" + Pattern string `json:"pattern,omitempty"` + // Regex defines if the pattern is a regular expression. If false the pattern will be used only for exact matches. + // + // +optional + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch",displayName="Regex" + Regex bool `json:"regex,omitempty"` + // Types defines the list of query types that should be considered for blocking. + // + // +optional + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Query Types" + Types BlockedQueryTypes `json:"types,omitempty"` +} + +// PerTenantQueryLimitSpec defines the limits applied to per tenant query path. +type PerTenantQueryLimitSpec struct { + QueryLimitSpec `json:",omitempty"` + + // Blocked defines the list of rules to block matching queries. + // + // +optional + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Blocked" + Blocked []BlockedQuerySpec `json:"blocked,omitempty"` +} + // IngestionLimitSpec defines the limits applied at the ingestion path. type IngestionLimitSpec struct { // IngestionRate defines the sample size per second. Units MB. @@ -773,6 +834,27 @@ type LimitsTemplateSpec struct { Retention *RetentionLimitSpec `json:"retention,omitempty"` } +// LimitsTemplateSpec defines the limits applied at ingestion or query path. +type PerTenantLimitsTemplateSpec struct { + // IngestionLimits defines the limits applied on ingested log streams. + // + // +optional + // +kubebuilder:validation:Optional + IngestionLimits *IngestionLimitSpec `json:"ingestion,omitempty"` + + // QueryLimits defines the limit applied on querying log streams. + // + // +optional + // +kubebuilder:validation:Optional + QueryLimits *PerTenantQueryLimitSpec `json:"queries,omitempty"` + + // Retention defines how long logs are kept in storage. + // + // +optional + // +kubebuilder:validation:Optional + Retention *RetentionLimitSpec `json:"retention,omitempty"` +} + // LimitsSpec defines the spec for limits applied at ingestion or query // path across the cluster or per tenant. type LimitsSpec struct { @@ -788,7 +870,7 @@ type LimitsSpec struct { // +optional // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Limits per Tenant" - Tenants map[string]LimitsTemplateSpec `json:"tenants,omitempty"` + Tenants map[string]PerTenantLimitsTemplateSpec `json:"tenants,omitempty"` } // RulesSpec defines the spec for the ruler component. @@ -1148,3 +1230,12 @@ func init() { // Hub declares the v1.LokiStack as the hub CRD version. func (*LokiStack) Hub() {} + +func (t BlockedQueryTypes) String() string { + res := make([]string, 0, len(t)) + for _, t := range t { + res = append(res, string(t)) + } + + return strings.Join(res, ",") +} diff --git a/operator/apis/loki/v1/zz_generated.deepcopy.go b/operator/apis/loki/v1/zz_generated.deepcopy.go index b29ddc93872e1..03b8e5ad0b9ed 100644 --- a/operator/apis/loki/v1/zz_generated.deepcopy.go +++ b/operator/apis/loki/v1/zz_generated.deepcopy.go @@ -430,6 +430,45 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BlockedQuerySpec) DeepCopyInto(out *BlockedQuerySpec) { + *out = *in + if in.Types != nil { + in, out := &in.Types, &out.Types + *out = make(BlockedQueryTypes, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockedQuerySpec. +func (in *BlockedQuerySpec) DeepCopy() *BlockedQuerySpec { + if in == nil { + return nil + } + out := new(BlockedQuerySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in BlockedQueryTypes) DeepCopyInto(out *BlockedQueryTypes) { + { + in := &in + *out = make(BlockedQueryTypes, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockedQueryTypes. +func (in BlockedQueryTypes) DeepCopy() BlockedQueryTypes { + if in == nil { + return nil + } + out := new(BlockedQueryTypes) + in.DeepCopyInto(out) + return *out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CASpec) DeepCopyInto(out *CASpec) { *out = *in @@ -505,7 +544,7 @@ func (in *LimitsSpec) DeepCopyInto(out *LimitsSpec) { } if in.Tenants != nil { in, out := &in.Tenants, &out.Tenants - *out = make(map[string]LimitsTemplateSpec, len(*in)) + *out = make(map[string]PerTenantLimitsTemplateSpec, len(*in)) for key, val := range *in { (*out)[key] = *val.DeepCopy() } @@ -1105,6 +1144,59 @@ func (in *OpenshiftTenantSpec) DeepCopy() *OpenshiftTenantSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PerTenantLimitsTemplateSpec) DeepCopyInto(out *PerTenantLimitsTemplateSpec) { + *out = *in + if in.IngestionLimits != nil { + in, out := &in.IngestionLimits, &out.IngestionLimits + *out = new(IngestionLimitSpec) + **out = **in + } + if in.QueryLimits != nil { + in, out := &in.QueryLimits, &out.QueryLimits + *out = new(PerTenantQueryLimitSpec) + (*in).DeepCopyInto(*out) + } + if in.Retention != nil { + in, out := &in.Retention, &out.Retention + *out = new(RetentionLimitSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerTenantLimitsTemplateSpec. +func (in *PerTenantLimitsTemplateSpec) DeepCopy() *PerTenantLimitsTemplateSpec { + if in == nil { + return nil + } + out := new(PerTenantLimitsTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PerTenantQueryLimitSpec) DeepCopyInto(out *PerTenantQueryLimitSpec) { + *out = *in + out.QueryLimitSpec = in.QueryLimitSpec + if in.Blocked != nil { + in, out := &in.Blocked, &out.Blocked + *out = make([]BlockedQuerySpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerTenantQueryLimitSpec. +func (in *PerTenantQueryLimitSpec) DeepCopy() *PerTenantQueryLimitSpec { + if in == nil { + return nil + } + out := new(PerTenantQueryLimitSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in PodStatusMap) DeepCopyInto(out *PodStatusMap) { { diff --git a/operator/apis/loki/v1beta1/lokistack_types.go b/operator/apis/loki/v1beta1/lokistack_types.go index 43cd34130d34c..7aa127951b4ae 100644 --- a/operator/apis/loki/v1beta1/lokistack_types.go +++ b/operator/apis/loki/v1beta1/lokistack_types.go @@ -933,11 +933,11 @@ func (src *LokiStack) ConvertTo(dstRaw conversion.Hub) error { } if len(src.Spec.Limits.Tenants) > 0 { - dst.Spec.Limits.Tenants = make(map[string]v1.LimitsTemplateSpec) + dst.Spec.Limits.Tenants = make(map[string]v1.PerTenantLimitsTemplateSpec) } for tenant, srcSpec := range src.Spec.Limits.Tenants { - dstSpec := v1.LimitsTemplateSpec{} + dstSpec := v1.PerTenantLimitsTemplateSpec{} if srcSpec.IngestionLimits != nil { dstSpec.IngestionLimits = &v1.IngestionLimitSpec{ @@ -952,10 +952,12 @@ func (src *LokiStack) ConvertTo(dstRaw conversion.Hub) error { } if srcSpec.QueryLimits != nil { - dstSpec.QueryLimits = &v1.QueryLimitSpec{ - MaxEntriesLimitPerQuery: srcSpec.QueryLimits.MaxEntriesLimitPerQuery, - MaxChunksPerQuery: srcSpec.QueryLimits.MaxChunksPerQuery, - MaxQuerySeries: srcSpec.QueryLimits.MaxQuerySeries, + dstSpec.QueryLimits = &v1.PerTenantQueryLimitSpec{ + QueryLimitSpec: v1.QueryLimitSpec{ + MaxEntriesLimitPerQuery: srcSpec.QueryLimits.MaxEntriesLimitPerQuery, + MaxChunksPerQuery: srcSpec.QueryLimits.MaxChunksPerQuery, + MaxQuerySeries: srcSpec.QueryLimits.MaxQuerySeries, + }, } } diff --git a/operator/bundle/community-openshift/manifests/loki-operator.clusterserviceversion.yaml b/operator/bundle/community-openshift/manifests/loki-operator.clusterserviceversion.yaml index c432c376acca6..f025ccc751d08 100644 --- a/operator/bundle/community-openshift/manifests/loki-operator.clusterserviceversion.yaml +++ b/operator/bundle/community-openshift/manifests/loki-operator.clusterserviceversion.yaml @@ -150,7 +150,7 @@ metadata: categories: OpenShift Optional, Logging & Tracing certified: "false" containerImage: docker.io/grafana/loki-operator:0.5.0 - createdAt: "2023-11-23T11:25:33Z" + createdAt: "2023-11-03T11:44:16Z" description: The Community Loki Operator provides Kubernetes native deployment and management of Loki and related logging components. operators.operatorframework.io/builder: operator-sdk-unknown @@ -444,6 +444,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/bundle/community-openshift/manifests/loki.grafana.com_lokistacks.yaml b/operator/bundle/community-openshift/manifests/loki.grafana.com_lokistacks.yaml index 267d1e292a4c0..a8033e692214e 100644 --- a/operator/bundle/community-openshift/manifests/loki.grafana.com_lokistacks.yaml +++ b/operator/bundle/community-openshift/manifests/loki.grafana.com_lokistacks.yaml @@ -289,6 +289,43 @@ spec: description: QueryLimits defines the limit applied on querying log streams. properties: + blocked: + description: Blocked defines the list of rules to block + matching queries. + items: + description: BlockedQuerySpec defines the rule spec + for queries to be blocked. + minProperties: 1 + properties: + hash: + description: Hash is a 32-bit FNV-1 hash of the + query string. + format: int32 + type: integer + pattern: + description: Pattern defines the pattern matching + the queries to be blocked. + type: string + regex: + description: Regex defines if the pattern is a + regular expression. If false the pattern will + be used only for exact matches. + type: boolean + types: + description: Types defines the list of query types + that should be considered for blocking. + items: + description: BlockedQueryType defines which + type of query a blocked query should apply + to. + enum: + - filter + - limited + - metric + type: string + type: array + type: object + type: array cardinalityLimit: description: CardinalityLimit defines the cardinality limit for index queries. diff --git a/operator/bundle/community/manifests/loki-operator.clusterserviceversion.yaml b/operator/bundle/community/manifests/loki-operator.clusterserviceversion.yaml index 9264955ed23fc..f1724fe77d8a3 100644 --- a/operator/bundle/community/manifests/loki-operator.clusterserviceversion.yaml +++ b/operator/bundle/community/manifests/loki-operator.clusterserviceversion.yaml @@ -150,7 +150,7 @@ metadata: categories: OpenShift Optional, Logging & Tracing certified: "false" containerImage: docker.io/grafana/loki-operator:0.5.0 - createdAt: "2023-11-23T11:25:30Z" + createdAt: "2023-11-03T11:44:14Z" description: The Community Loki Operator provides Kubernetes native deployment and management of Loki and related logging components. operators.operatorframework.io/builder: operator-sdk-unknown @@ -444,6 +444,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/bundle/community/manifests/loki.grafana.com_lokistacks.yaml b/operator/bundle/community/manifests/loki.grafana.com_lokistacks.yaml index 5e21aa0b11d5a..8b86ddfff8bbf 100644 --- a/operator/bundle/community/manifests/loki.grafana.com_lokistacks.yaml +++ b/operator/bundle/community/manifests/loki.grafana.com_lokistacks.yaml @@ -289,6 +289,43 @@ spec: description: QueryLimits defines the limit applied on querying log streams. properties: + blocked: + description: Blocked defines the list of rules to block + matching queries. + items: + description: BlockedQuerySpec defines the rule spec + for queries to be blocked. + minProperties: 1 + properties: + hash: + description: Hash is a 32-bit FNV-1 hash of the + query string. + format: int32 + type: integer + pattern: + description: Pattern defines the pattern matching + the queries to be blocked. + type: string + regex: + description: Regex defines if the pattern is a + regular expression. If false the pattern will + be used only for exact matches. + type: boolean + types: + description: Types defines the list of query types + that should be considered for blocking. + items: + description: BlockedQueryType defines which + type of query a blocked query should apply + to. + enum: + - filter + - limited + - metric + type: string + type: array + type: object + type: array cardinalityLimit: description: CardinalityLimit defines the cardinality limit for index queries. diff --git a/operator/bundle/openshift/manifests/loki-operator.clusterserviceversion.yaml b/operator/bundle/openshift/manifests/loki-operator.clusterserviceversion.yaml index 2139a813749ac..90bdb078cbf35 100644 --- a/operator/bundle/openshift/manifests/loki-operator.clusterserviceversion.yaml +++ b/operator/bundle/openshift/manifests/loki-operator.clusterserviceversion.yaml @@ -150,7 +150,7 @@ metadata: categories: OpenShift Optional, Logging & Tracing certified: "false" containerImage: quay.io/openshift-logging/loki-operator:0.1.0 - createdAt: "2023-11-23T11:25:35Z" + createdAt: "2023-11-03T11:44:18Z" description: | The Loki Operator for OCP provides a means for configuring and managing a Loki stack for cluster logging. ## Prerequisites and Requirements @@ -457,6 +457,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/bundle/openshift/manifests/loki.grafana.com_lokistacks.yaml b/operator/bundle/openshift/manifests/loki.grafana.com_lokistacks.yaml index 087fd1a97cddf..f121699ec6fb8 100644 --- a/operator/bundle/openshift/manifests/loki.grafana.com_lokistacks.yaml +++ b/operator/bundle/openshift/manifests/loki.grafana.com_lokistacks.yaml @@ -289,6 +289,43 @@ spec: description: QueryLimits defines the limit applied on querying log streams. properties: + blocked: + description: Blocked defines the list of rules to block + matching queries. + items: + description: BlockedQuerySpec defines the rule spec + for queries to be blocked. + minProperties: 1 + properties: + hash: + description: Hash is a 32-bit FNV-1 hash of the + query string. + format: int32 + type: integer + pattern: + description: Pattern defines the pattern matching + the queries to be blocked. + type: string + regex: + description: Regex defines if the pattern is a + regular expression. If false the pattern will + be used only for exact matches. + type: boolean + types: + description: Types defines the list of query types + that should be considered for blocking. + items: + description: BlockedQueryType defines which + type of query a blocked query should apply + to. + enum: + - filter + - limited + - metric + type: string + type: array + type: object + type: array cardinalityLimit: description: CardinalityLimit defines the cardinality limit for index queries. diff --git a/operator/config/crd/bases/loki.grafana.com_lokistacks.yaml b/operator/config/crd/bases/loki.grafana.com_lokistacks.yaml index 199836ca130e3..4661097811b75 100644 --- a/operator/config/crd/bases/loki.grafana.com_lokistacks.yaml +++ b/operator/config/crd/bases/loki.grafana.com_lokistacks.yaml @@ -271,6 +271,43 @@ spec: description: QueryLimits defines the limit applied on querying log streams. properties: + blocked: + description: Blocked defines the list of rules to block + matching queries. + items: + description: BlockedQuerySpec defines the rule spec + for queries to be blocked. + minProperties: 1 + properties: + hash: + description: Hash is a 32-bit FNV-1 hash of the + query string. + format: int32 + type: integer + pattern: + description: Pattern defines the pattern matching + the queries to be blocked. + type: string + regex: + description: Regex defines if the pattern is a + regular expression. If false the pattern will + be used only for exact matches. + type: boolean + types: + description: Types defines the list of query types + that should be considered for blocking. + items: + description: BlockedQueryType defines which + type of query a blocked query should apply + to. + enum: + - filter + - limited + - metric + type: string + type: array + type: object + type: array cardinalityLimit: description: CardinalityLimit defines the cardinality limit for index queries. diff --git a/operator/config/manifests/community-openshift/bases/loki-operator.clusterserviceversion.yaml b/operator/config/manifests/community-openshift/bases/loki-operator.clusterserviceversion.yaml index a8db185fa67ae..b171014a40694 100644 --- a/operator/config/manifests/community-openshift/bases/loki-operator.clusterserviceversion.yaml +++ b/operator/config/manifests/community-openshift/bases/loki-operator.clusterserviceversion.yaml @@ -357,6 +357,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/config/manifests/community/bases/loki-operator.clusterserviceversion.yaml b/operator/config/manifests/community/bases/loki-operator.clusterserviceversion.yaml index 49f5cdcb809d1..79a71267ab746 100644 --- a/operator/config/manifests/community/bases/loki-operator.clusterserviceversion.yaml +++ b/operator/config/manifests/community/bases/loki-operator.clusterserviceversion.yaml @@ -357,6 +357,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/config/manifests/openshift/bases/loki-operator.clusterserviceversion.yaml b/operator/config/manifests/openshift/bases/loki-operator.clusterserviceversion.yaml index 9455549c3b40e..20c923c23cc8b 100644 --- a/operator/config/manifests/openshift/bases/loki-operator.clusterserviceversion.yaml +++ b/operator/config/manifests/openshift/bases/loki-operator.clusterserviceversion.yaml @@ -369,6 +369,27 @@ spec: path: limits.tenants.ingestion.perStreamRateLimitBurst x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number + - description: Blocked defines the list of rules to block matching queries. + displayName: Blocked + path: limits.tenants.queries.blocked + - description: Hash is a 32-bit FNV-1 hash of the query string. + displayName: Query Hash + path: limits.tenants.queries.blocked[0].hash + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Pattern defines the pattern matching the queries to be blocked. + displayName: Query Pattern + path: limits.tenants.queries.blocked[0].pattern + - description: Regex defines if the pattern is a regular expression. If false + the pattern will be used only for exact matches. + displayName: Regex + path: limits.tenants.queries.blocked[0].regex + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Types defines the list of query types that should be considered + for blocking. + displayName: Query Types + path: limits.tenants.queries.blocked[0].types - description: CardinalityLimit defines the cardinality limit for index queries. displayName: Cardinality Limit path: limits.tenants.queries.cardinalityLimit diff --git a/operator/docs/operator/api.md b/operator/docs/operator/api.md index e415bc9daa214..f2ee194a87a2a 100644 --- a/operator/docs/operator/api.md +++ b/operator/docs/operator/api.md @@ -902,6 +902,107 @@ OPASpec +## BlockedQuerySpec { #loki-grafana-com-v1-BlockedQuerySpec } +

+(Appears on:PerTenantQueryLimitSpec) +

+
+

BlockedQuerySpec defines the rule spec for queries to be blocked.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+hash
+ +int32 + +
+(Optional) +

Hash is a 32-bit FNV-1 hash of the query string.

+
+pattern
+ +string + +
+(Optional) +

Pattern defines the pattern matching the queries to be blocked.

+
+regex
+ +bool + +
+(Optional) +

Regex defines if the pattern is a regular expression. If false the pattern will be used only for exact matches.

+
+types
+ + +BlockedQueryTypes + + +
+(Optional) +

Types defines the list of query types that should be considered for blocking.

+
+ +## BlockedQueryType { #loki-grafana-com-v1-BlockedQueryType } +(string alias) +
+

BlockedQueryType defines which type of query a blocked query should apply to.

+
+ + + + + + + + + + + + + + +
ValueDescription

"filter"

BlockedQueryFilter is used, when the blocked query should apply to queries using a log filter.

+

"limited"

BlockedQueryLimited is used, when the blocked query should apply to queries without a filter or a metric aggregation.

+

"metric"

BlockedQueryMetric is used, when the blocked query should apply to queries with an aggregation.

+
+ +## BlockedQueryTypes { #loki-grafana-com-v1-BlockedQueryTypes } +([]github.com/grafana/loki/operator/apis/loki/v1.BlockedQueryType alias) +

+(Appears on:BlockedQuerySpec) +

+
+

BlockedQueryTypes defines a slice of BlockedQueryType values to be used for a blocked query.

+
+ ## CASpec { #loki-grafana-com-v1-CASpec }

(Appears on:MTLSSpec, OIDCSpec, ObjectStorageTLSSpec) @@ -1067,7 +1168,7 @@ MemberListSpec ## IngestionLimitSpec { #loki-grafana-com-v1-IngestionLimitSpec }

-(Appears on:LimitsTemplateSpec) +(Appears on:LimitsTemplateSpec, PerTenantLimitsTemplateSpec)

IngestionLimitSpec defines the limits applied at the ingestion path.

@@ -1268,8 +1369,8 @@ LimitsTemplateSpec tenants
- -map[string]github.com/grafana/loki/operator/apis/loki/v1.LimitsTemplateSpec + +map[string]github.com/grafana/loki/operator/apis/loki/v1.PerTenantLimitsTemplateSpec @@ -2718,6 +2819,110 @@ Setting this to an empty array disables admin groups.

+## PerTenantLimitsTemplateSpec { #loki-grafana-com-v1-PerTenantLimitsTemplateSpec } +

+(Appears on:LimitsSpec) +

+
+

LimitsTemplateSpec defines the limits applied at ingestion or query path.

+
+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ingestion
+ + +IngestionLimitSpec + + +
+(Optional) +

IngestionLimits defines the limits applied on ingested log streams.

+
+queries
+ + +PerTenantQueryLimitSpec + + +
+(Optional) +

QueryLimits defines the limit applied on querying log streams.

+
+retention
+ + +RetentionLimitSpec + + +
+(Optional) +

Retention defines how long logs are kept in storage.

+
+ +## PerTenantQueryLimitSpec { #loki-grafana-com-v1-PerTenantQueryLimitSpec } +

+(Appears on:PerTenantLimitsTemplateSpec) +

+
+

PerTenantQueryLimitSpec defines the limits applied to per tenant query path.

+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+QueryLimitSpec
+ + +QueryLimitSpec + + +
+
+blocked
+ + +[]BlockedQuerySpec + + +
+(Optional) +

Blocked defines the list of rules to block matching queries.

+
+ ## PermissionType { #loki-grafana-com-v1-PermissionType } (string alias)

@@ -2762,7 +2967,7 @@ Setting this to an empty array disables admin groups.

## QueryLimitSpec { #loki-grafana-com-v1-QueryLimitSpec }

-(Appears on:LimitsTemplateSpec) +(Appears on:LimitsTemplateSpec, PerTenantQueryLimitSpec)

QueryLimitSpec defines the limits applies at the query path.

@@ -3588,7 +3793,7 @@ IMPORTANT: Make sure that the replication factor defined is less than or equal t ## RetentionLimitSpec { #loki-grafana-com-v1-RetentionLimitSpec }

-(Appears on:LimitsTemplateSpec) +(Appears on:LimitsTemplateSpec, PerTenantLimitsTemplateSpec)

RetentionLimitSpec controls how long logs will be kept in storage.

diff --git a/operator/internal/manifests/config_test.go b/operator/internal/manifests/config_test.go index 5df65eb709cc5..b58cac99e1083 100644 --- a/operator/internal/manifests/config_test.go +++ b/operator/internal/manifests/config_test.go @@ -84,7 +84,7 @@ func randomConfigOptions() Options { MaxQuerySeries: rand.Int31(), }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ uuid.New().String(): { IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: rand.Int31(), @@ -97,10 +97,12 @@ func randomConfigOptions() Options { PerStreamRateLimit: rand.Int31(), PerStreamRateLimitBurst: rand.Int31(), }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxEntriesLimitPerQuery: rand.Int31(), - MaxChunksPerQuery: rand.Int31(), - MaxQuerySeries: rand.Int31(), + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxEntriesLimitPerQuery: rand.Int31(), + MaxChunksPerQuery: rand.Int31(), + MaxQuerySeries: rand.Int31(), + }, }, }, }, @@ -375,7 +377,7 @@ func TestConfigOptions_RetentionConfig(t *testing.T) { Days: 14, }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "development": { Retention: &lokiv1.RetentionLimitSpec{ Days: 3, @@ -394,7 +396,7 @@ func TestConfigOptions_RetentionConfig(t *testing.T) { spec: lokiv1.LokiStackSpec{ Size: lokiv1.SizeOneXExtraSmall, Limits: &lokiv1.LimitsSpec{ - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "development": { Retention: &lokiv1.RetentionLimitSpec{ Days: 3, @@ -1092,10 +1094,12 @@ func TestConfigOptions_RulerOverrides_OCPUserWorkloadOnlyEnabled(t *testing.T) { Enabled: true, }, Limits: &lokiv1.LimitsSpec{ - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "application": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "5m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "5m", + }, }, }, }, @@ -1132,9 +1136,11 @@ func TestConfigOptions_RulerOverrides_OCPUserWorkloadOnlyEnabled(t *testing.T) { }, wantOverridesOptions: map[string]config.LokiOverrides{ "application": { - Limits: lokiv1.LimitsTemplateSpec{ - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "5m", + Limits: lokiv1.PerTenantLimitsTemplateSpec{ + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "5m", + }, }, }, Ruler: config.RulerOverrides{ diff --git a/operator/internal/manifests/internal/config/build.go b/operator/internal/manifests/internal/config/build.go index 399e9efd493c8..f599b791a7949 100644 --- a/operator/internal/manifests/internal/config/build.go +++ b/operator/internal/manifests/internal/config/build.go @@ -4,6 +4,8 @@ import ( "bytes" "embed" "io" + "reflect" + "strings" "text/template" "github.com/ViaQ/logerr/v2/kverrors" @@ -27,7 +29,9 @@ var ( lokiConfigYAMLTmpl = template.Must(template.ParseFS(lokiConfigYAMLTmplFile, "loki-config.yaml")) - lokiRuntimeConfigYAMLTmpl = template.Must(template.ParseFS(lokiRuntimeConfigYAMLTmplFile, "loki-runtime-config.yaml")) + lokiRuntimeConfigYAMLTmpl = template.Must(template.New("loki-runtime-config.yaml").Funcs(template.FuncMap{ + "yamlBlock": yamlBlock, + }).ParseFS(lokiRuntimeConfigYAMLTmplFile, "loki-runtime-config.yaml")) ) // Build builds a loki stack configuration files @@ -54,3 +58,9 @@ func Build(opts Options) ([]byte, []byte, error) { } return cfg, rcfg, nil } + +func yamlBlock(indent string, in reflect.Value) string { + inStr := in.String() + lines := strings.Split(strings.TrimRight(inStr, "\n"), "\n") + return strings.Join(lines, "\n"+indent) +} diff --git a/operator/internal/manifests/internal/config/build_test.go b/operator/internal/manifests/internal/config/build_test.go index fd254b7ee1e9d..8b448008c82d8 100644 --- a/operator/internal/manifests/internal/config/build_test.go +++ b/operator/internal/manifests/internal/config/build_test.go @@ -444,6 +444,15 @@ overrides: ingestion_burst_size_mb: 5 max_global_streams_per_user: 1 max_chunks_per_query: 1000000 + blocked_queries: + - hash: 12345 + types: metric,limited + - pattern: | + .*prod.* + regex: true + - types: metric + - pattern: | + sum(rate({env="prod"}[1m])) ` opts := Options{ Stack: lokiv1.LokiStackSpec{ @@ -472,15 +481,33 @@ overrides: CardinalityLimit: 100000, }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "test-a": { IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, IngestionBurstSize: 5, MaxGlobalStreamsPerTenant: 1, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, + Blocked: []lokiv1.BlockedQuerySpec{ + { + Hash: 12345, + Types: lokiv1.BlockedQueryTypes{lokiv1.BlockedQueryMetric, lokiv1.BlockedQueryLimited}, + }, + { + Pattern: ".*prod.*", + Regex: true, + }, + { + Types: lokiv1.BlockedQueryTypes{lokiv1.BlockedQueryMetric}, + }, + { + Pattern: `sum(rate({env="prod"}[1m]))`, + }, + }, }, }, }, @@ -488,14 +515,32 @@ overrides: }, Overrides: map[string]LokiOverrides{ "test-a": { - Limits: lokiv1.LimitsTemplateSpec{ + Limits: lokiv1.PerTenantLimitsTemplateSpec{ IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, MaxGlobalStreamsPerTenant: 1, IngestionBurstSize: 5, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, + Blocked: []lokiv1.BlockedQuerySpec{ + { + Hash: 12345, + Types: lokiv1.BlockedQueryTypes{lokiv1.BlockedQueryMetric, lokiv1.BlockedQueryLimited}, + }, + { + Pattern: ".*prod.*", + Regex: true, + }, + { + Types: lokiv1.BlockedQueryTypes{lokiv1.BlockedQueryMetric}, + }, + { + Pattern: `sum(rate({env="prod"}[1m]))`, + }, + }, }, }, }, @@ -1977,15 +2022,17 @@ overrides: }, }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "test-a": { IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, IngestionBurstSize: 5, MaxGlobalStreamsPerTenant: 1, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, Retention: &lokiv1.RetentionLimitSpec{ Days: 7, @@ -2003,14 +2050,16 @@ overrides: }, Overrides: map[string]LokiOverrides{ "test-a": { - Limits: lokiv1.LimitsTemplateSpec{ + Limits: lokiv1.PerTenantLimitsTemplateSpec{ IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, IngestionBurstSize: 5, MaxGlobalStreamsPerTenant: 1, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, Retention: &lokiv1.RetentionLimitSpec{ Days: 7, @@ -4350,15 +4399,17 @@ overrides: CardinalityLimit: 100000, }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "test-a": { IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, IngestionBurstSize: 5, MaxGlobalStreamsPerTenant: 1, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, }, }, @@ -4366,14 +4417,16 @@ overrides: }, Overrides: map[string]LokiOverrides{ "test-a": { - Limits: lokiv1.LimitsTemplateSpec{ + Limits: lokiv1.PerTenantLimitsTemplateSpec{ IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, MaxGlobalStreamsPerTenant: 1, IngestionBurstSize: 5, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, }, }, @@ -4646,15 +4699,17 @@ overrides: CardinalityLimit: 100000, }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "test-a": { IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, IngestionBurstSize: 5, MaxGlobalStreamsPerTenant: 1, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, }, }, @@ -4662,14 +4717,16 @@ overrides: }, Overrides: map[string]LokiOverrides{ "test-a": { - Limits: lokiv1.LimitsTemplateSpec{ + Limits: lokiv1.PerTenantLimitsTemplateSpec{ IngestionLimits: &lokiv1.IngestionLimitSpec{ IngestionRate: 2, MaxGlobalStreamsPerTenant: 1, IngestionBurstSize: 5, }, - QueryLimits: &lokiv1.QueryLimitSpec{ - MaxChunksPerQuery: 1000000, + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + MaxChunksPerQuery: 1000000, + }, }, }, }, diff --git a/operator/internal/manifests/internal/config/loki-runtime-config.yaml b/operator/internal/manifests/internal/config/loki-runtime-config.yaml index 8b2fe60b23f8e..421426cb3911f 100644 --- a/operator/internal/manifests/internal/config/loki-runtime-config.yaml +++ b/operator/internal/manifests/internal/config/loki-runtime-config.yaml @@ -54,6 +54,24 @@ overrides: {{- if $spec.QueryLimits.CardinalityLimit }} cardinality_limit: {{ $spec.QueryLimits.CardinalityLimit }} {{- end }} + {{- with $l.Blocked }} + blocked_queries: + {{- range $blockedQuery := . }} + - {{ with $blockedQuery.Pattern -}} + pattern: | + {{ . | yamlBlock " " }} + {{ end -}} + {{- with $blockedQuery.Regex }} + regex: {{ . }} + {{- end }} + {{- with $blockedQuery.Types }} + types: {{ . }} + {{- end }} + {{- with $blockedQuery.Hash }} + hash: {{ . }} + {{- end }} + {{- end }} + {{- end}} {{- end -}} {{- with $spec.Retention }} retention_period: {{ .Days }}d diff --git a/operator/internal/manifests/internal/config/options.go b/operator/internal/manifests/internal/config/options.go index 5829270244322..110bce9ee8df3 100644 --- a/operator/internal/manifests/internal/config/options.go +++ b/operator/internal/manifests/internal/config/options.go @@ -41,7 +41,7 @@ type Options struct { } type LokiOverrides struct { - Limits lokiv1.LimitsTemplateSpec + Limits lokiv1.PerTenantLimitsTemplateSpec Ruler RulerOverrides } diff --git a/operator/internal/manifests/options_test.go b/operator/internal/manifests/options_test.go index 48e9853f7870a..bf297adc650ff 100644 --- a/operator/internal/manifests/options_test.go +++ b/operator/internal/manifests/options_test.go @@ -60,15 +60,19 @@ func TestNewTimeoutConfig_ReturnsCustomConfig_WhenLimitsSpecNotEmpty_UseMaxTenan QueryTimeout: "10m", }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "tenant-a": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "10m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "10m", + }, }, }, "tenant-b": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "20m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "20m", + }, }, }, }, @@ -99,15 +103,19 @@ func TestNewTimeoutConfig_ReturnsCustomConfig_WhenTenantLimitsSpecOnly_ReturnsUs s := lokiv1.LokiStack{ Spec: lokiv1.LokiStackSpec{ Limits: &lokiv1.LimitsSpec{ - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "tenant-a": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "10m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "10m", + }, }, }, "tenant-b": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "20m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "20m", + }, }, }, }, @@ -160,15 +168,19 @@ func TestNewTimeoutConfig_ReturnsDefaults_WhenTenantQueryTimeoutParseError(t *te QueryTimeout: "10m", }, }, - Tenants: map[string]lokiv1.LimitsTemplateSpec{ + Tenants: map[string]lokiv1.PerTenantLimitsTemplateSpec{ "tenant-a": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "invalid", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "invalid", + }, }, }, "tenant-b": { - QueryLimits: &lokiv1.QueryLimitSpec{ - QueryTimeout: "20m", + QueryLimits: &lokiv1.PerTenantQueryLimitSpec{ + QueryLimitSpec: lokiv1.QueryLimitSpec{ + QueryTimeout: "20m", + }, }, }, }, diff --git a/operator/internal/metrics/metrics.go b/operator/internal/metrics/metrics.go index fcf82ddca5d69..3c994f13c61ef 100644 --- a/operator/internal/metrics/metrics.go +++ b/operator/internal/metrics/metrics.go @@ -142,7 +142,7 @@ func boolValue(value bool) float64 { return 0 } -func streamRate(tenantLimits map[string]lokiv1.LimitsTemplateSpec, ingesters int32) float64 { +func streamRate(tenantLimits map[string]lokiv1.PerTenantLimitsTemplateSpec, ingesters int32) float64 { var tenants, tenantStreamLimit int32 = 0, 0 for _, tenant := range tenantLimits {