mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-10 06:24:09 +09:00
feat(monitoring): add optional email receiver to alertmanager (#3800)
## What this PR does Adds an optional email receiver configured through `alerta.alerts.email`. It is disabled by default. Alerts carrying `notify_email="true"` are emailed when their severity is in `severities`, which defaults to critical and major. `alertnames` also selects platform alerts without changing their rules. Earlier heartbeat and blackhole routes keep precedence. Email routes preserve the Alerta copy through a preceding route with `continue: true`, and they inherit the root `group_by`, so Alerta and email agree on how many notifications one alert produces. The SMTP password is read from a Secret with a fixed name, `alertmanager-email-password`, mounted through `VMAlertmanager.spec.secrets` and referenced by `auth_password_file` when `authUsername` is set. The platform operator creates that Secret. The name is not configurable, because a tenant-chosen name would let a `Monitoring` writer mount any Secret of the namespace into Alertmanager and send its `password` key to an SMTP host of their choosing, and no tenant role can read those Secrets by any other route. `to` takes an address or a comma-separated list, and `from` takes one address, each with an optional display name. The accepted form is narrower than RFC 5322 on purpose, so that a bad address fails the render instead of being dropped when the first alert fires. The local part must be a dot-atom. A display name is a run of atoms or quoted strings without the specials `net/mail` rejects in a phrase. A domain literal must hold a dotted-quad IPv4 address. IPv6 literals are rejected because their syntax differs across Go mail parser versions. Template actions are rejected, because Alertmanager expands both fields as templates before it parses them. Quoted local parts, comments and a pasted `mailto:` prefix fail the render as well. `smarthost` must be `host:port`, where the host is a host name or a bracketed IP address. A bracketed value must be a valid IPv4 or IPv6 address, so `[deadbeef]:25` and `[1:2:3:4::5:6:7:8]:25` fail the render. The port must be between 1 and 65535 and must not have leading zeros, so `smtp.example.org:0465` fails too. `repeatInterval` is checked with Alertmanager's own duration grammar and limits. Units go in descending order, each at most once, and the value must be non-zero and below the int64 overflow, so what renders is what Alertmanager loads. Partial configuration fails the render and names the fields still set, so clearing the addresses to turn email off tells the operator which leftovers to clear. Subject and body templates are not exposed. Alertmanager parses them per notification, and a broken one surfaces only in a log the tenant cannot read. Checks run for this change. - The monitoring chart suites pass with 228 tests in `packages/system/monitoring` and 16 in `packages/extra/monitoring`. 117 of them are in the two email test files. - 234 address inputs were rendered through the chart. 91 were accepted and 143 rejected. Every accepted input executes as a template and passes `net/mail.ParseAddressList`, including the one-address check for `from`, on Go 1.25.8, 1.26.4 and 1.27.1. - Widening the IPv4 octet from `25[0-5]` to `25[0-9]` fails 4 tests. Putting back the loose `\[[0-9A-Fa-f:.]+\]` domain literal fails 19 tests. Replacing the group-count guard for compressed IPv6 smarthosts with `true` fails the `[1:2:3:4::5:6:7:8]:25` test. - `make generate` with cozyvalues-gen v1.6.0 leaves the tree unchanged. SMTP delivery against a real relay has not been tested. ### Screenshots No dashboard/UI change. ### Downstream repositories Walked the trigger map against the diff. `packages/extra/monitoring` gains values fields, so its README and schema changed. `monitoring` is in the website Makefile `SERVICES` list, and that reference page regenerates from `README.md` automatically on the next stable tag, so there is no manual follow-up to link. The terraform provider does not model the monitoring service, as there is no such resource under `internal/provider`, so there is nothing to update there either. No package is added or renamed, and no CRD, tooling or node contract is touched. - [x] No downstream repository is affected by this change - [ ] [cozystack/website](https://github.com/cozystack/website) - follow-up: - [ ] [cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack) - follow-up: - [ ] [cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) - follow-up: - [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up: - [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up: - [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) - follow-up: - [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) - follow-up: - [ ] [cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server) - follow-up: - [ ] [cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) - follow-up: - [ ] [cozystack/examples](https://github.com/cozystack/examples) - follow-up: ### Release note ```release-note feat(monitoring): add optional email alerting through alerta.alerts.email, with configurable severity and alert-name selection and an SMTP password read from the fixed Secret alertmanager-email-password ```
This commit is contained in:
8 files changed
+1629
-22
No files matched your search
@@ -86,26 +86,34 @@
|
||||
|
||||
### Alerta configuration
|
||||
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------------------- | --------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `alerta` | Configuration for the Alerta service. | `object` | `{}` |
|
||||
| `alerta.storage` | Persistent volume size for the database. | `string` | `10Gi` |
|
||||
| `alerta.storageClassName` | StorageClass used for the database. | `string` | `""` |
|
||||
| `alerta.resources` | Resource configuration. | `object` | `{}` |
|
||||
| `alerta.resources.requests` | Resource requests. | `object` | `{}` |
|
||||
| `alerta.resources.requests.cpu` | CPU request. | `quantity` | `100m` |
|
||||
| `alerta.resources.requests.memory` | Memory request. | `quantity` | `256Mi` |
|
||||
| `alerta.resources.limits` | Resource limits. | `object` | `{}` |
|
||||
| `alerta.resources.limits.cpu` | CPU limit. | `quantity` | `1` |
|
||||
| `alerta.resources.limits.memory` | Memory limit. | `quantity` | `1Gi` |
|
||||
| `alerta.alerts` | Alert routing configuration. | `object` | `{}` |
|
||||
| `alerta.alerts.telegram` | Configuration for Telegram alerts. | `object` | `{}` |
|
||||
| `alerta.alerts.telegram.token` | Telegram bot token. | `string` | `""` |
|
||||
| `alerta.alerts.telegram.chatID` | Telegram chat ID(s), separated by commas. | `string` | `""` |
|
||||
| `alerta.alerts.telegram.disabledSeverity` | List of severities without alerts (e.g. ["informational","warning"]). | `[]string` | `[]` |
|
||||
| `alerta.alerts.slack` | Configuration for Slack alerts. | `object` | `{}` |
|
||||
| `alerta.alerts.slack.url` | Configuration uri for Slack alerts. | `string` | `""` |
|
||||
| `alerta.alerts.slack.disabledSeverity` | List of severities without alerts (e.g. ["informational","warning"]). | `[]string` | `[]` |
|
||||
| Name | Description | Type | Value |
|
||||
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
|
||||
| `alerta` | Configuration for the Alerta service. | `object` | `{}` |
|
||||
| `alerta.storage` | Persistent volume size for the database. | `string` | `10Gi` |
|
||||
| `alerta.storageClassName` | StorageClass used for the database. | `string` | `""` |
|
||||
| `alerta.resources` | Resource configuration. | `object` | `{}` |
|
||||
| `alerta.resources.requests` | Resource requests. | `object` | `{}` |
|
||||
| `alerta.resources.requests.cpu` | CPU request. | `quantity` | `100m` |
|
||||
| `alerta.resources.requests.memory` | Memory request. | `quantity` | `256Mi` |
|
||||
| `alerta.resources.limits` | Resource limits. | `object` | `{}` |
|
||||
| `alerta.resources.limits.cpu` | CPU limit. | `quantity` | `1` |
|
||||
| `alerta.resources.limits.memory` | Memory limit. | `quantity` | `1Gi` |
|
||||
| `alerta.alerts` | Alert routing configuration. | `object` | `{}` |
|
||||
| `alerta.alerts.telegram` | Configuration for Telegram alerts. | `object` | `{}` |
|
||||
| `alerta.alerts.telegram.token` | Telegram bot token. | `string` | `""` |
|
||||
| `alerta.alerts.telegram.chatID` | Telegram chat ID(s), separated by commas. | `string` | `""` |
|
||||
| `alerta.alerts.telegram.disabledSeverity` | List of severities without alerts (e.g. ["informational","warning"]). | `[]string` | `[]` |
|
||||
| `alerta.alerts.slack` | Configuration for Slack alerts. | `object` | `{}` |
|
||||
| `alerta.alerts.slack.url` | Configuration uri for Slack alerts. | `string` | `""` |
|
||||
| `alerta.alerts.slack.disabledSeverity` | List of severities without alerts (e.g. ["informational","warning"]). | `[]string` | `[]` |
|
||||
| `alerta.alerts.email` | Configuration for email alerts. Alerts carrying the label notify_email with the string value true are emailed when their severity is in the severities list (default critical and major). A bare YAML boolean does not match. Alerts listed in alertnames are emailed unless matched by an earlier platform route. | `object` | `{}` |
|
||||
| `alerta.alerts.email.to` | Recipient address, or several separated by commas. A display name is accepted, such as `Oncall <oncall@example.org>`, as long as it carries no comma. Quote display names containing punctuation such as `:`, `@`, parentheses or `?`. RFC 2047 encoded words are not accepted. IP domain literals accept dotted-quad IPv4 only. IPv6 literals are rejected because Go mail parsers disagree on their syntax across versions. ASCII control characters are rejected. Addresses must be literal, so Alertmanager template actions are rejected. The accepted form is deliberately narrower than RFC 5322. The local part must be a dot-atom, with no leading, trailing or doubled dot, and quoted local parts, comments and a `mailto:` prefix are rejected. An address outside that form fails the render, because Alertmanager parses addresses only when it sends and drops the notification with no record a tenant can read. | `string` | `""` |
|
||||
| `alerta.alerts.email.from` | Sender address, one only. A display name is accepted. It takes the same narrower form as `to`, and an address outside it fails the render. | `string` | `""` |
|
||||
| `alerta.alerts.email.smarthost` | SMTP server as `host:port` (e.g. "smtp.example.com:465"). A value without a port, an invalid bracketed IP address or a port with leading zeros fails the render. Port 465 uses implicit TLS, other ports use STARTTLS. | `string` | `""` |
|
||||
| `alerta.alerts.email.authUsername` | Username for SMTP LOGIN/PLAIN authentication. The password is read from the `password` key of a Secret named `alertmanager-email-password` in the release namespace, which the platform operator creates. The name is fixed and the Secret is mounted into Alertmanager, so a missing Secret blocks the whole Alertmanager rollout, not only email delivery. The credential in it must belong to this tenant alone. `smarthost` is chosen by whoever writes the Monitoring, so one relay credential provisioned under the same name in every namespace can be collected by pointing `smarthost` at a host the tenant controls. | `string` | `""` |
|
||||
| `alerta.alerts.email.repeatInterval` | Minimum time before a still-firing alert is emailed again, as an Alertmanager duration with units `y`, `w`, `d`, `h`, `m`, `s`, `ms` in descending order, each at most once, such as `5m`, `12h` or `1h30m`. Delivery is evaluated every 5m, so shorter intervals take effect at 5m and other intervals round up to a multiple of 5m. Zero, a unit out of order and a total beyond what Alertmanager accepts fail the render. Empty keeps the 12h default. | `string` | `""` |
|
||||
| `alerta.alerts.email.alertnames` | Alert names emailed whether or not the rule carries the notify_email label, with no severity filter. Earlier platform routes still take precedence. Alerts with `event="Heartbeat"`, including `Watchdog`, go only to Alerta, and alerts with severity `none`, `CDIDefaultStorageClassDegraded` and `CDINoDefaultStorageClass` are blackholed and never reach email. This is the way to opt in alerts the platform ships, since their helm-owned rule definitions cannot be labelled per cluster. Entries must be plain Prometheus alert names such as `KubeAPIDown`, and anything else fails the render. Empty adds no extra route. | `[]string` | `[]` |
|
||||
| `alerta.alerts.email.severities` | Severities the notify_email route accepts (e.g. ["critical","major","warning"]). Empty keeps the default of critical and major. List every severity in use to email opted-in alerts regardless of severity. Entries must be plain severity names, and anything else fails the render. | `[]string` | `[]` |
|
||||
|
||||
|
||||
### Grafana configuration
|
||||
|
||||
@@ -506,6 +506,59 @@
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"properties": {
|
||||
"email": {
|
||||
"description": "Configuration for email alerts. Alerts carrying the label notify_email with the string value true are emailed when their severity is in the severities list (default critical and major). A bare YAML boolean does not match. Alerts listed in alertnames are emailed unless matched by an earlier platform route.",
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"required": [
|
||||
"from",
|
||||
"smarthost",
|
||||
"to"
|
||||
],
|
||||
"properties": {
|
||||
"alertnames": {
|
||||
"description": "Alert names emailed whether or not the rule carries the notify_email label, with no severity filter. Earlier platform routes still take precedence. Alerts with `event=\"Heartbeat\"`, including `Watchdog`, go only to Alerta, and alerts with severity `none`, `CDIDefaultStorageClassDegraded` and `CDINoDefaultStorageClass` are blackholed and never reach email. This is the way to opt in alerts the platform ships, since their helm-owned rule definitions cannot be labelled per cluster. Entries must be plain Prometheus alert names such as `KubeAPIDown`, and anything else fails the render. Empty adds no extra route.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"authUsername": {
|
||||
"description": "Username for SMTP LOGIN/PLAIN authentication. The password is read from the `password` key of a Secret named `alertmanager-email-password` in the release namespace, which the platform operator creates. The name is fixed and the Secret is mounted into Alertmanager, so a missing Secret blocks the whole Alertmanager rollout, not only email delivery. The credential in it must belong to this tenant alone. `smarthost` is chosen by whoever writes the Monitoring, so one relay credential provisioned under the same name in every namespace can be collected by pointing `smarthost` at a host the tenant controls.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"from": {
|
||||
"description": "Sender address, one only. A display name is accepted. It takes the same narrower form as `to`, and an address outside it fails the render.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"repeatInterval": {
|
||||
"description": "Minimum time before a still-firing alert is emailed again, as an Alertmanager duration with units `y`, `w`, `d`, `h`, `m`, `s`, `ms` in descending order, each at most once, such as `5m`, `12h` or `1h30m`. Delivery is evaluated every 5m, so shorter intervals take effect at 5m and other intervals round up to a multiple of 5m. Zero, a unit out of order and a total beyond what Alertmanager accepts fail the render. Empty keeps the 12h default.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"severities": {
|
||||
"description": "Severities the notify_email route accepts (e.g. [\"critical\",\"major\",\"warning\"]). Empty keeps the default of critical and major. List every severity in use to email opted-in alerts regardless of severity. Entries must be plain severity names, and anything else fails the render.",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"smarthost": {
|
||||
"description": "SMTP server as `host:port` (e.g. \"smtp.example.com:465\"). A value without a port, an invalid bracketed IP address or a port with leading zeros fails the render. Port 465 uses implicit TLS, other ports use STARTTLS.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"to": {
|
||||
"description": "Recipient address, or several separated by commas. A display name is accepted, such as `Oncall \u003concall@example.org\u003e`, as long as it carries no comma. Quote display names containing punctuation such as `:`, `@`, parentheses or `?`. RFC 2047 encoded words are not accepted. IP domain literals accept dotted-quad IPv4 only. IPv6 literals are rejected because Go mail parsers disagree on their syntax across versions. ASCII control characters are rejected. Addresses must be literal, so Alertmanager template actions are rejected. The accepted form is deliberately narrower than RFC 5322. The local part must be a dot-atom, with no leading, trailing or doubled dot, and quoted local parts, comments and a `mailto:` prefix are rejected. An address outside that form fails the render, because Alertmanager parses addresses only when it sends and drops the notification with no record a tenant can read.",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"slack": {
|
||||
"description": "Configuration for Slack alerts.",
|
||||
"type": "object",
|
||||
|
||||
@@ -152,9 +152,19 @@ tracingCollector:
|
||||
## @field {string} url - Configuration uri for Slack alerts.
|
||||
## @field {[]string} [disabledSeverity] - List of severities without alerts (e.g. ["informational","warning"]).
|
||||
|
||||
## @typedef {struct} EmailAlerts - Email alert configuration. When enabled, alerts carrying the label `notify_email="true"` with a severity from `severities` (default `critical` and `major`) are sent by email in addition to Alerta, and alerts listed in `alertnames` are emailed regardless of labels unless matched by an earlier platform route. The label is matched as a string, so a rule must carry `notify_email: "true"` rather than a bare YAML boolean.
|
||||
## @field {string} to - Recipient address, or several separated by commas. A display name is accepted, such as `Oncall <oncall@example.org>`, as long as it carries no comma. Quote display names containing punctuation such as `:`, `@`, parentheses or `?`. RFC 2047 encoded words are not accepted. IP domain literals accept dotted-quad IPv4 only. IPv6 literals are rejected because Go mail parsers disagree on their syntax across versions. ASCII control characters are rejected. Addresses must be literal, so Alertmanager template actions are rejected. The accepted form is deliberately narrower than RFC 5322. The local part must be a dot-atom, with no leading, trailing or doubled dot, and quoted local parts, comments and a `mailto:` prefix are rejected. An address outside that form fails the render, because Alertmanager parses addresses only when it sends and drops the notification with no record a tenant can read.
|
||||
## @field {string} from - Sender address, one only. A display name is accepted. It takes the same narrower form as `to`, and an address outside it fails the render.
|
||||
## @field {string} smarthost - SMTP server as `host:port` (e.g. "smtp.example.com:465"). A value without a port, an invalid bracketed IP address or a port with leading zeros fails the render. Port 465 uses implicit TLS, other ports use STARTTLS.
|
||||
## @field {string} [authUsername] - Username for SMTP LOGIN/PLAIN authentication. The password is read from the `password` key of a Secret named `alertmanager-email-password` in the release namespace, which the platform operator creates. The name is fixed and the Secret is mounted into Alertmanager, so a missing Secret blocks the whole Alertmanager rollout, not only email delivery. The credential in it must belong to this tenant alone. `smarthost` is chosen by whoever writes the Monitoring, so one relay credential provisioned under the same name in every namespace can be collected by pointing `smarthost` at a host the tenant controls.
|
||||
## @field {string} [repeatInterval] - Minimum time before a still-firing alert is emailed again, as an Alertmanager duration with units `y`, `w`, `d`, `h`, `m`, `s`, `ms` in descending order, each at most once, such as `5m`, `12h` or `1h30m`. Delivery is evaluated every 5m, so shorter intervals take effect at 5m and other intervals round up to a multiple of 5m. Zero, a unit out of order and a total beyond what Alertmanager accepts fail the render. Empty keeps the 12h default.
|
||||
## @field {[]string} [alertnames] - Alert names emailed whether or not the rule carries the notify_email label, with no severity filter. Earlier platform routes still take precedence. Alerts with `event="Heartbeat"`, including `Watchdog`, go only to Alerta, and alerts with severity `none`, `CDIDefaultStorageClassDegraded` and `CDINoDefaultStorageClass` are blackholed and never reach email. This is the way to opt in alerts the platform ships, since their helm-owned rule definitions cannot be labelled per cluster. Entries must be plain Prometheus alert names such as `KubeAPIDown`, and anything else fails the render. Empty adds no extra route.
|
||||
## @field {[]string} [severities] - Severities the notify_email route accepts (e.g. ["critical","major","warning"]). Empty keeps the default of critical and major. List every severity in use to email opted-in alerts regardless of severity. Entries must be plain severity names, and anything else fails the render.
|
||||
|
||||
## @typedef {struct} Alerts - Alert routing configuration.
|
||||
## @field {TelegramAlerts} [telegram] - Configuration for Telegram alerts.
|
||||
## @field {SlackAlerts} [slack] - Configuration for Slack alerts.
|
||||
## @field {EmailAlerts} [email] - Configuration for email alerts. Alerts carrying the label notify_email with the string value true are emailed when their severity is in the severities list (default critical and major). A bare YAML boolean does not match. Alerts listed in alertnames are emailed unless matched by an earlier platform route.
|
||||
|
||||
## @typedef {struct} Alerta - Configuration for the Alerta service.
|
||||
## @field {string} [storage] - Persistent volume size for the database.
|
||||
@@ -181,6 +191,14 @@ alerta:
|
||||
slack:
|
||||
url: ""
|
||||
disabledSeverity: []
|
||||
email:
|
||||
to: ""
|
||||
from: ""
|
||||
smarthost: ""
|
||||
authUsername: ""
|
||||
repeatInterval: ""
|
||||
alertnames: []
|
||||
severities: []
|
||||
##
|
||||
## @section Grafana configuration
|
||||
##
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ spec:
|
||||
singular: monitoring
|
||||
plural: monitorings
|
||||
openAPISchema: |-
|
||||
{"title":"Chart Values","type":"object","properties":{"host":{"description":"The hostname used to access Grafana externally (defaults to 'grafana' subdomain for the tenant host).","type":"string","default":""},"metricsStorages":{"description":"Configuration of metrics storage instances.","type":"array","default":[{"deduplicationInterval":"15s","name":"shortterm","retentionPeriod":"3d","storage":"10Gi","storageClassName":""},{"deduplicationInterval":"5m","name":"longterm","retentionPeriod":"14d","storage":"10Gi","storageClassName":""}],"items":{"type":"object","required":["deduplicationInterval","name","retentionPeriod","storage"],"properties":{"deduplicationInterval":{"description":"Deduplication interval for metrics.","type":"string"},"name":{"description":"Name of the storage instance.","type":"string"},"retentionPeriod":{"description":"Retention period for metrics.","type":"string"},"storage":{"description":"Persistent volume size.","type":"string","default":"10Gi"},"storageClassName":{"description":"StorageClass used for the data.","type":"string"},"vminsert":{"description":"Configuration for vminsert.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}},"vmselect":{"description":"Configuration for vmselect.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}},"vmstorage":{"description":"Configuration for vmstorage.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0Line truncated
|
||||
{"title":"Chart Values","type":"object","properties":{"host":{"description":"The hostname used to access Grafana externally (defaults to 'grafana' subdomain for the tenant host).","type":"string","default":""},"metricsStorages":{"description":"Configuration of metrics storage instances.","type":"array","default":[{"deduplicationInterval":"15s","name":"shortterm","retentionPeriod":"3d","storage":"10Gi","storageClassName":""},{"deduplicationInterval":"5m","name":"longterm","retentionPeriod":"14d","storage":"10Gi","storageClassName":""}],"items":{"type":"object","required":["deduplicationInterval","name","retentionPeriod","storage"],"properties":{"deduplicationInterval":{"description":"Deduplication interval for metrics.","type":"string"},"name":{"description":"Name of the storage instance.","type":"string"},"retentionPeriod":{"description":"Retention period for metrics.","type":"string"},"storage":{"description":"Persistent volume size.","type":"string","default":"10Gi"},"storageClassName":{"description":"StorageClass used for the data.","type":"string"},"vminsert":{"description":"Configuration for vminsert.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}},"vmselect":{"description":"Configuration for vmselect.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}}}},"vmstorage":{"description":"Configuration for vmstorage.","type":"object","properties":{"maxAllowed":{"description":"Maximum allowed resources.","type":"object","properties":{"cpu":{"description":"CPU limit.","default":1,"pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory limit.","default":"1Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"minAllowed":{"description":"Minimum guaranteed resources.","type":"object","properties":{"cpu":{"description":"CPU request.","default":"100m","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory request.","default":"256Mi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0Line truncated
|
||||
release:
|
||||
prefix: ""
|
||||
labels:
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
description: Monitoring and observability stack
|
||||
module: true
|
||||
icon: PHN2ZyB3aWR0aD0iMTQ0IiBoZWlnaHQ9IjE0NCIgdmlld0JveD0iMCAwIDE0NCAxNDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxNDQiIGhlaWdodD0iMTQ0IiByeD0iMjQiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl82ODdfMzI2OCkiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzY4N18zMjY4KSI+CjxwYXRoIGQ9Ik04OS41MDM5IDExMS43MDdINTQuNDk3QzU0LjE3MjcgMTExLjcwNyA1NC4wMTA4IDExMS4yMjEgNTQuMzM0OSAxMTEuMDU5TDU3LjI1MjIgMTA4Ljk1MkM2MC4zMzE0IDEwNi42ODMgNjEuOTUyMiAxMDIuNjMxIDYwLjk3OTcgOTguNzQxMkg4My4wMjFDODIuMDQ4NSAxMDIuNjMxIDgzLjY2OTMgMTA2LjY4MyA4Ni43NDg1IDEwOC45NTJMODkuNjY1OCAxMTEuMDU5Qzg5Ljk5IDExMS4yMjEgODkuODI3OSAxMTEuNzA3IDg5LjUwMzkgMTExLjcwN1oiIGZpbGw9IiNCMEI2QkIiLz4KPHBhdGggZD0iTTExMy4zMjggOTguNzQxSDMwLjY3MjVDMjcuNTkzMSA5OC43NDEgMjUgOTYuMTQ4IDI1IDkzLjA2ODdWMzMuMTAzMkMyNSAzMC4wMjM5IDI3LjU5MzEgMjcuNDMwNyAzMC42NzI1IDI3LjQzMDdIMTEzLjMyOEMxMTYuNDA3IDI3LjQzMDcgMTE5IDMwLjAyMzcgMTE5IDMzLjEwMzJWOTMuMDY4N0MxMTkgOTYuMTQ4IDExNi40MDcgOTguNzQxIDExMy4zMjggOTguNzQxWiIgZmlsbD0iI0U4RURFRSIvPgo8cGF0aCBkPSJNMTE5IDg0LjE1NDlIMjVWMzMuMTAzMkMyNSAzMC4wMjM5IDI3LjU5MzEgMjcuNDMwNyAzMC42NzI1IDI3LjQzMDdIMTEzLjMyOEMxMTYuNDA3IDI3LjQzMDcgMTE5IDMwLjAyMzcgMTE5IDMzLjEwMzJMMTE5IDg0LjE1NDlaIiBmaWxsPSIjMzg0NTRGIi8+CjxwYXRoIGQ9Ik05MC42Mzc0IDExNi41NjlINTMuMzYxNkM1Mi4wNjUxIDExNi41NjkgNTAuOTMwNyAxMTUuNDM1IDUwLjkzMDcgMTE0LjEzOEM1MC45MzA3IDExMi44NDEgNTIuMDY1MSAxMTEuNzA3IDUzLjM2MTYgMTExLjcwN0g5MC42Mzc0QzkxLjkzMzkgMTExLjcwNyA5My4wNjg0IDExMi44NDEgOTMuMDY4NCAxMTQuMTM4QzkzLjA2ODQgMTE1LjQzNSA5MS45MzM5IDExNi41NjkgOTAuNjM3NCAxMTYuNTY5WiIgZmlsbD0iI0U4RURFRSIvPgo8cGF0aCBkPSJNNTQuMTcyMiAzOC43NzU3SDMzLjEwMzJDMzIuMTMwNyAzOC43NzU3IDMxLjQ4MjQgMzguMTI3NCAzMS40ODI0IDM3LjE1NDlDMzEuNDgyNCAzNi4xODI0IDMyLjEzMDcgMzUuNTM0MiAzMy4xMDMyIDM1LjUzNDJINTQuMTcyMkM1NS4xNDQ3IDM1LjUzNDIgNTUuNzkzIDM2LjE4MjQgNTUuNzkzIDM3LjE1NDlDNTUuNzkyOCAzOC4xMjc0IDU1LjE0NDUgMzguNzc1NyA1NC4xNzIyIDM4Ljc3NTdaIiBmaWxsPSIjREQzNDJFIi8+CjxwYXRoIGQ9Ik02My44OTYzIDQ1LjI1OTFINDEuMjA2N0M0MC4yMzQyIDQ1LjI1OTEgMzkuNTg1OSA0NC42MTA4IDM5LjU4NTkgNDMuNjM4M0MzOS41ODU5IDQyLjY2NTggNDAuMjM0MiA0Mi4wMTc2IDQxLjIwNjcgNDIuMDE3Nkg2My44OTYzQzY0Ljg2ODggNDIuMDE3NiA2NS41MTcxIDQyLjY2NTggNjUuNTE3MSA0My42MzgzQzY1LjUxNzEgNDQuNjEwOCA2NC44Njg4IDQ1LjI1OTEgNjMuODk2MyA0NS4yNTkxWiIgZmlsbD0iIzczODNCRiIvPgo8cGF0aCBkPSJNMzQuNzI0IDQ1LjI1OTFIMzMuMTAzMkMzMi4xMzA3IDQ1LjI1OTEgMzEuNDgyNCA0NC42MTA4IDMxLjQ4MjQgNDMuNjM4M0MzMS40ODI0IDQyLjY2NTggMzIuMTMwNyA0Mi4wMTc2IDMzLjEwMzIgNDIuMDE3NkgzNC43MjRDMzUuNjk2NCA0Mi4wMTc2IDM2LjM0NDcgNDIuNjY1OCAzNi4zNDQ3IDQzLjYzODNDMzYuMzQ0NyA0NC42MTA4IDM1LjY5NjMgNDUuMjU5MSAzNC43MjQgNDUuMjU5MVoiIGZpbGw9IiM0MkIwNUMiLz4KPHBhdGggZD0iTTYzLjg5NjMgMzguNzc1N0g2MC42NTQ5QzU5LjY4MjQgMzguNzc1NyA1OS4wMzQyIDM4LjEyNzQgNTkuMDM0MiAzNy4xNTQ5QzU5LjAzNDIgMzYuMTgyNCA1OS42ODI0IDM1LjUzNDIgNjAuNjU0OSAzNS41MzQySDYzLjg5NjNDNjQuODY4OCAzNS41MzQyIDY1LjUxNzEgMzYuMTgyNCA2NS41MTcxIDM3LjE1NDlDNjUuNTE3MSAzOC4xMjc0IDY0Ljg2ODggMzguNzc1NyA2My44OTYzIDM4Ljc3NTdaIiBmaWxsPSIjRUNCQTE2Ii8+CjxwYXRoIGQ9Ik00Ny42ODkzIDUxLjc0MTNIMzMuMTAzMkMzMi4xMzA3IDUxLjc0MTMgMzEuNDgyNCA1MS4wOTMxIDMxLjQ4MjQgNTAuMTIwNkMzMS40ODI0IDQ5LjE0ODEgMzIuMTMwNyA0OC41IDMzLjEwMzIgNDguNUg0Ny42ODkzQzQ4LjY2MTggNDguNSA0OS4zMTAxIDQ5LjE0ODMgNDkuMzEwMSA1MC4xMjA4QzQ5LjMxMDEgNTEuMDkzMyA0OC42NjE4IDUxLjc0MTMgNDcuNjg5MyA1MS43NDEzWiIgZmlsbD0iI0REMzQyRSIvPgo8cGF0aCBkPSJNNjMuODk2OCA1MS43NDEzSDU0LjE3MjVDNTMuMiA1MS43NDEzIDUyLjU1MTggNTEuMDkzMSA1Mi41NTE4IDUwLjEyMDZDNTIuNTUxOCA0OS4xNDgxIDUzLjIwMDIgNDguNSA1NC4xNzI3IDQ4LjVINjMuODk2OUM2NC44Njk0IDQ4LjUgNjUuNTE3NyA0OS4xNDgzIDY1LjUxNzcgNTAuMTIwOEM2NS41MTc3IDUxLjA5MzMgNjQuODY5MiA1MS43NDEzIDYzLjg5NjggNTEuNzQxM1oiIGZpbGw9IiNFQ0JBMTYiLz4KPHBhdGggZD0iTTU0LjE3MjIgNTguMjI0SDMzLjEwMzJDMzIuMTMwNyA1OC4yMjQgMzEuNDgyNCA1Ny41NzU3IDMxLjQ4MjQgNTYuNjAzMkMzMS40ODI0IDU1LjYzMDcgMzIuMTMwNyA1NC45ODI0IDMzLjEwMzIgNTQuOTgyNEg1NC4xNzIyQzU1LjE0NDcgNTQuOTgyNCA1NS43OTMgNTUuNjMwNyA1NS43OTMgNTYuNjAzMkM1NS43OTMgNTcuNTc1NyA1NS4xNDQ1IDU4LjIyNCA1NC4xNzIyIDU4LjIyNFoiIGZpbGw9IiM0MkIwNUMiLz4KPHBhdGggZD0iTTYzLjg5NjMgNjQuNzA3NEg0MS4yMDY3QzQwLjIzNDIgNjQuNzA3NCAzOS41ODU5IDY0LjA1OTEgMzkuNTg1OSA2My4wODY2QzM5LjU4NTkgNjIuMTE0MSA0MC4yMzQyIDYxLjQ2NTggNDEuMjA2NyA2MS40NjU4SDYzLjg5NjNDNjQuODY4OCA2MS40NjU4IDY1LjUxNzEgNjIuMTE0MSA2NS41MTcxIDYzLjA4NjZDNjUuNTE3MSA2NC4wNTkxIDY0Ljg2ODggNjQuNzA3NCA2My44OTYzIDY0LjcwNzRaIiBmaWxsPSIjRUNCQTE2Ii8+CjxwYXRoIGQ9Ik0zNC43MjQgNjQuNzA3NEgzMy4xMDMyQzMyLjEzMDcgNjQuNzA3NCAzMS40ODI0IDY0LjA1OTEgMzEuNDgyNCA2My4wODY2QzMxLjQ4MjQgNjIuMTE0MSAzMi4xMzA3IDYxLjQ2NTggMzMuMTAzMiA2MS40NjU4SDM0LjcyNEMzNS42OTY0IDYxLjQ2NTggMzYuMzQ0NyA2Mi4xMTQxIDM2LjM0NDcgNjMuMDg2NkMzNi4zNDQ3IDY0LjA1OTEgMzUuNjk2MyA2NC43MDc0IDM0LjcyNCA2NC43MDc0WiIgZmlsbD0iI0REMzQyRSIvPgo8cGF0aCBkPSJNNDcuNjg5MyA3MS4xODk4SDMzLjEwMzJDMzIuMTMwNyA3MS4xODk4IDMxLjQ4MjQgNzAuNTQxNSAzMS40ODI0IDY5LjU2OUMzMS40ODI0IDY4LjU5NjUgMzIuMTMwNyA2Ny45NDgyIDMzLjEwMzIgNjcuOTQ4Mkg0Ny42ODkzQzQ4LjY2MTggNjcuOTQ4MiA0OS4zMTAxIDY4LjU5NjUgNDkuMzEwMSA2OS41NjlDNDkuMzEwMSA3MC41NDE1IDQ4LjY2MTggNzEuMTg5OCA0Ny42ODkzIDcxLjE4OThaIiBmaWxsPSIjNDJCMDVDIi8+CjxwYXRoIGQ9Ik02My44OTY4IDcxLjE4OThINTQuMTcyNUM1My4yIDcxLjE4OTggNTIuNTUxOCA3MC41NDE1IDUyLjU1MTggNjkuNTY5QzUyLjU1MTggNjguNTk2NSA1My4yIDY3Ljk0ODIgNTQuMLine truncated
|
||||
keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "metricsStorages"], ["spec", "logsStorages"], ["spec", "tracingStorages"], ["spec", "tracingCollector"], ["spec", "tracingCollector", "enabled"], ["spec", "tracingCollector", "replicas"], ["spec", "tracingCollector", "samplingPercentage"], ["spec", "tracingCollector", "redactAttributes"], ["spec", "tracingCollector", "resources"], ["spec", "tracingCollector", "resources", "limits"], ["spec", "tracingCollector", "resources", "limits", "cpu"], ["spec", "tracingCollector", "resources", "limits", "memory"], ["spec", "tracingCollector", "resources", "requests"], ["spec", "tracingCollector", "resources", "requests", "cpu"], ["spec", "tracingCollector", "resources", "requests", "memory"], ["spec", "alerta"], ["spec", "alerta", "storage"], ["spec", "alerta", "storageClassName"], ["spec", "alerta", "resources"], ["spec", "alerta", "resources", "limits"], ["spec", "alerta", "resources", "limits", "cpu"], ["spec", "alerta", "resources", "limits", "memory"], ["spec", "alerta", "resources", "requests"], ["spec", "alerta", "resources", "requests", "cpu"], ["spec", "alerta", "resources", "requests", "memory"], ["spec", "alerta", "alerts"], ["spec", "alerta", "alerts", "telegram"], ["spec", "alerta", "alerts", "telegram", "token"], ["spec", "alerta", "alerts", "telegram", "chatID"], ["spec", "alerta", "alerts", "telegram", "disabledSeverity"], ["spec", "alerta", "alerts", "slack"], ["spec", "alerta", "alerts", "slack", "url"], ["spec", "alerta", "alerts", "slack", "disabledSeverity"], ["spec", "grafana"], ["spec", "grafana", "db"], ["spec", "grafana", "db", "size"], ["spec", "grafana", "resources"], ["spec", "grafana", "resources", "limits"], ["spec", "grafana", "resources", "limits", "cpu"], ["spec", "grafana", "resources", "limits", "memory"], ["spec", "grafana", "resources", "requests"], ["spec", "grafana", "resources", "requests", "cpu"], ["spec", "grafana", "resources", "requests", "memory"], ["spec", "vmagent"], ["spec", "vmagent", "externalLabels"], ["spec", "vmagent", "externalLabels", "cluster"], ["spec", "vmagent", "remoteWrite"], ["spec", "vmagent", "remoteWrite", "urls"], ["spec", "oidc"], ["spec", "oidc", "mode"], ["spec", "oidc", "customConfig"], ["spec", "oidc", "customConfig", "config"], ["spec", "oidc", "customConfig", "secretRef"], ["spec", "oidc", "customConfig", "secretRef", "name"], ["spec", "oidc", "users"]]
|
||||
keysOrder: [["apiVersion"], ["appVersion"], ["kind"], ["metadata"], ["metadata", "name"], ["spec", "host"], ["spec", "metricsStorages"], ["spec", "logsStorages"], ["spec", "tracingStorages"], ["spec", "tracingCollector"], ["spec", "tracingCollector", "enabled"], ["spec", "tracingCollector", "replicas"], ["spec", "tracingCollector", "samplingPercentage"], ["spec", "tracingCollector", "redactAttributes"], ["spec", "tracingCollector", "resources"], ["spec", "tracingCollector", "resources", "limits"], ["spec", "tracingCollector", "resources", "limits", "cpu"], ["spec", "tracingCollector", "resources", "limits", "memory"], ["spec", "tracingCollector", "resources", "requests"], ["spec", "tracingCollector", "resources", "requests", "cpu"], ["spec", "tracingCollector", "resources", "requests", "memory"], ["spec", "alerta"], ["spec", "alerta", "storage"], ["spec", "alerta", "storageClassName"], ["spec", "alerta", "resources"], ["spec", "alerta", "resources", "limits"], ["spec", "alerta", "resources", "limits", "cpu"], ["spec", "alerta", "resources", "limits", "memory"], ["spec", "alerta", "resources", "requests"], ["spec", "alerta", "resources", "requests", "cpu"], ["spec", "alerta", "resources", "requests", "memory"], ["spec", "alerta", "alerts"], ["spec", "alerta", "alerts", "telegram"], ["spec", "alerta", "alerts", "telegram", "token"], ["spec", "alerta", "alerts", "telegram", "chatID"], ["spec", "alerta", "alerts", "telegram", "disabledSeverity"], ["spec", "alerta", "alerts", "slack"], ["spec", "alerta", "alerts", "slack", "url"], ["spec", "alerta", "alerts", "slack", "disabledSeverity"], ["spec", "alerta", "alerts", "email"], ["spec", "alerta", "alerts", "email", "to"], ["spec", "alerta", "alerts", "email", "from"], ["spec", "alerta", "alerts", "email", "smarthost"], ["spec", "alerta", "alerts", "email", "authUsername"], ["spec", "alerta", "alerts", "email", "repeatInterval"], ["spec", "alerta", "alerts", "email", "alertnames"], ["spec", "alerta", "alerts", "email", "severities"], ["spec", "grafana"], ["spec", "grafana", "db"], ["spec", "grafana", "db", "size"], ["spec", "grafana", "resources"], ["spec", "grafana", "resources", "limits"], ["spec", "grafana", "resources", "limits", "cpu"], ["spec", "grafana", "resources", "limits", "memory"], ["spec", "grafana", "resources", "requests"], ["spec", "grafana", "resources", "requests", "cpu"], ["spec", "grafana", "resources", "requests", "memory"], ["spec", "vmagent"], ["spec", "vmagent", "externalLabels"], ["spec", "vmagent", "externalLabels", "cluster"], ["spec", "vmagent", "remoteWrite"], ["spec", "vmagent", "remoteWrite", "urls"], ["spec", "oidc"], ["spec", "oidc", "mode"], ["spec", "oidc", "customConfig"], ["spec", "oidc", "customConfig", "config"], ["spec", "oidc", "customConfig", "secretRef"], ["spec", "oidc", "customConfig", "secretRef", "name"], ["spec", "oidc", "users"]]
|
||||
secrets:
|
||||
exclude: []
|
||||
include:
|
||||
|
||||
@@ -6,6 +6,103 @@
|
||||
{{- $gatewayEnabled := (index .Values._cluster "gateway-enabled") | default "false" }}
|
||||
{{- $wildcardSecret := (index .Values._cluster "wildcard-secret-name") | default "" }}
|
||||
|
||||
{{- $email := ((.Values.alerta.alerts).email) | default dict }}
|
||||
{{- $emailAlertnames := $email.alertnames | default list }}
|
||||
{{- $emailSeverities := $email.severities | default (list "critical" "major") }}
|
||||
{{- $emailPasswordSecret := "alertmanager-email-password" }}
|
||||
{{- $emailSet := list }}
|
||||
{{- range $field := list "to" "from" "smarthost" "authUsername" "repeatInterval" "alertnames" "severities" }}
|
||||
{{- if index $email $field }}{{ $emailSet = append $emailSet $field }}{{ end }}
|
||||
{{- end }}
|
||||
{{- $emailEnabled := gt (len $emailSet) 0 }}
|
||||
{{- if $emailEnabled }}
|
||||
{{- if not (and $email.to $email.smarthost $email.from) }}
|
||||
{{- fail (printf "alerta.alerts.email to, from and smarthost must all be set to enable email alerts. To turn email off, clear every field under alerta.alerts.email. Fields still set are %s" (join ", " $emailSet)) }}
|
||||
{{- end }}
|
||||
{{- $ipv4Octet := "(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])" }}
|
||||
{{- $ipv4 := printf "%s(\\.%s){3}" $ipv4Octet $ipv4Octet }}
|
||||
{{- $ipLiteral := printf "\\[%s\\]" $ipv4 }}
|
||||
{{- $mailboxAddr := printf "[A-Za-z0-9!#$%%&'*+/=?^_`{|}~-]+(\\.[A-Za-z0-9!#$%%&'*+/=?^_`{|}~-]+)*@(%s|[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*)" $ipLiteral }}
|
||||
{{- $nameAtom := "[^\\x00-\\x20\\x7f()<>\\[\\]:;@\\\\,\"?]+" }}
|
||||
{{- $nameQuoted := "\"([^\\x00-\\x1f\\x7f\"\\\\,]|\\\\[ -~])*\"" }}
|
||||
{{- $nameWord := printf "(%s|%s)" $nameAtom $nameQuoted }}
|
||||
{{- $displayName := printf "(%s( +%s)* *)?" $nameWord $nameWord }}
|
||||
{{- $mailbox := printf "^(%s|%s<%s>)$" $mailboxAddr $displayName $mailboxAddr }}
|
||||
{{- $emailFrom := trimAll " " (toString $email.from) }}
|
||||
{{- if contains "{{" $emailFrom }}
|
||||
{{- fail "alerta.alerts.email.from must contain a literal address, without template actions" }}
|
||||
{{- end }}
|
||||
{{- if not (regexMatch $mailbox $emailFrom) }}
|
||||
{{- fail (printf "alerta.alerts.email.from must be one address, such as alerts@example.org or Alerts <alerts@example.org>, got %q" $emailFrom) }}
|
||||
{{- end }}
|
||||
{{- range $recipient := splitList "," (toString $email.to) }}
|
||||
{{- $trimmed := trimAll " " $recipient }}
|
||||
{{- if contains "{{" $trimmed }}
|
||||
{{- fail "alerta.alerts.email.to must contain literal addresses, without template actions" }}
|
||||
{{- end }}
|
||||
{{- if eq $trimmed "" }}
|
||||
{{- fail (printf "alerta.alerts.email.to has an empty entry, got %q" (toString $email.to)) }}
|
||||
{{- end }}
|
||||
{{- if not (regexMatch $mailbox $trimmed) }}
|
||||
{{- fail (printf "alerta.alerts.email.to must be an address or a comma-separated list of addresses, such as oncall@example.org, got %q" $trimmed) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $smarthost := toString $email.smarthost }}
|
||||
{{- if not (regexMatch "^(\\[[0-9A-Fa-f:.]+\\]|[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*):[0-9]{1,5}$" $smarthost) }}
|
||||
{{- fail (printf "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got %q" $smarthost) }}
|
||||
{{- end }}
|
||||
{{- $smtpHost := regexReplaceAll ":[0-9]+$" $smarthost "" }}
|
||||
{{- if hasPrefix "[" $smtpHost }}
|
||||
{{- $ip := trimSuffix "]" (trimPrefix "[" $smtpHost) }}
|
||||
{{- $isIPv4 := regexMatch (printf "^%s$" $ipv4) $ip }}
|
||||
{{- $ip = regexReplaceAll (printf ":%s$" $ipv4) $ip ":0:0" }}
|
||||
{{- $hexGroups := "[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,6}" }}
|
||||
{{- $fullIPv6 := regexMatch "^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$" $ip }}
|
||||
{{- $compressedIPv6 := and (regexMatch (printf "^(%s)?::(%s)?$" $hexGroups $hexGroups) $ip) (lt (len (regexFindAll "[0-9A-Fa-f]+" $ip -1)) 8) }}
|
||||
{{- if not (or $isIPv4 $fullIPv6 $compressedIPv6) }}
|
||||
{{- fail (printf "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got %q" $smarthost) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $smtpPortText := regexReplaceAll "^.*:" $smarthost "" }}
|
||||
{{- if and (gt (len $smtpPortText) 1) (hasPrefix "0" $smtpPortText) }}
|
||||
{{- fail (printf "alerta.alerts.email.smarthost port must not contain leading zeros, got %q" $smarthost) }}
|
||||
{{- end }}
|
||||
{{- $smtpPort := int $smtpPortText }}
|
||||
{{- if or (lt $smtpPort 1) (gt $smtpPort 65535) }}
|
||||
{{- fail (printf "alerta.alerts.email.smarthost port must be between 1 and 65535, got %q" $smarthost) }}
|
||||
{{- end }}
|
||||
{{- if $email.repeatInterval }}
|
||||
{{- $repeat := toString $email.repeatInterval }}
|
||||
{{- if not (regexMatch "^([0-9]+y)?([0-9]+w)?([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s)?([0-9]+ms)?$" $repeat) }}
|
||||
{{- fail (printf "alerta.alerts.email.repeatInterval must be an Alertmanager duration with units in descending order, each at most once, such as 5m, 12h or 1h30m, got %q" $repeat) }}
|
||||
{{- end }}
|
||||
{{- $repeatMs := int64 0 }}
|
||||
{{- $maxRepeatMs := int64 9223372036854 }}
|
||||
{{- $unitMs := dict "y" 31536000000 "w" 604800000 "d" 86400000 "h" 3600000 "m" 60000 "s" 1000 "ms" 1 }}
|
||||
{{- range $part := regexFindAll "[0-9]+(ms|[ywdhms])" $repeat -1 }}
|
||||
{{- $amount := regexReplaceAll "^0+" (regexReplaceAll "[a-z]+$" $part "") "" | default "0" }}
|
||||
{{- $scale := index $unitMs (regexReplaceAll "^[0-9]+" $part "") }}
|
||||
{{- if or (gt (len $amount) 13) (gt (int64 $amount) (div (sub $maxRepeatMs $repeatMs) $scale)) }}
|
||||
{{- fail (printf "alerta.alerts.email.repeatInterval is out of range for Alertmanager, got %q" $repeat) }}
|
||||
{{- end }}
|
||||
{{- $repeatMs = add $repeatMs (mul (int64 $amount) $scale) }}
|
||||
{{- end }}
|
||||
{{- if eq (int64 $repeatMs) (int64 0) }}
|
||||
{{- fail (printf "alerta.alerts.email.repeatInterval cannot be zero, got %q" $repeat) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $name := $emailAlertnames }}
|
||||
{{- if not (regexMatch "^[a-zA-Z_:][a-zA-Z0-9_:]*$" (toString $name)) }}
|
||||
{{- fail (printf "alerta.alerts.email.alertnames entries must be Prometheus alert names, got %q" (toString $name)) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $severity := $emailSeverities }}
|
||||
{{- if not (regexMatch "^[a-zA-Z0-9_-]+$" (toString $severity)) }}
|
||||
{{- fail (printf "alerta.alerts.email.severities entries must be plain severity names, got %q" (toString $severity)) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- $apiKey := randAlphaNum 32 }}
|
||||
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "alerta" }}
|
||||
{{- if $existingSecret }}
|
||||
@@ -239,6 +336,8 @@ apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: alertmanager
|
||||
labels:
|
||||
app: alertmanager
|
||||
type: Opaque
|
||||
stringData:
|
||||
alertmanager.yaml: |
|
||||
@@ -261,6 +360,32 @@ stringData:
|
||||
- receiver: blackhole
|
||||
matchers:
|
||||
- 'alertname=~"CDIDefaultStorageClassDegraded|CDINoDefaultStorageClass"'
|
||||
{{- if $emailEnabled }}
|
||||
- receiver: alerta
|
||||
continue: true
|
||||
matchers:
|
||||
- 'severity=~"{{ join "|" $emailSeverities }}"'
|
||||
- 'notify_email="true"'
|
||||
- receiver: email
|
||||
group_wait: 1m
|
||||
group_interval: 5m
|
||||
repeat_interval: {{ $email.repeatInterval | default "12h" | quote }}
|
||||
matchers:
|
||||
- 'severity=~"{{ join "|" $emailSeverities }}"'
|
||||
- 'notify_email="true"'
|
||||
{{- if $emailAlertnames }}
|
||||
- receiver: alerta
|
||||
continue: true
|
||||
matchers:
|
||||
- 'alertname=~"^({{ join "|" $emailAlertnames }})$"'
|
||||
- receiver: email
|
||||
group_wait: 1m
|
||||
group_interval: 5m
|
||||
repeat_interval: {{ $email.repeatInterval | default "12h" | quote }}
|
||||
matchers:
|
||||
- 'alertname=~"^({{ join "|" $emailAlertnames }})$"'
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
receivers:
|
||||
- name: blackhole
|
||||
- name: "alerta"
|
||||
@@ -271,6 +396,18 @@ stringData:
|
||||
webhook_configs:
|
||||
- url: 'http://alerta/api/webhooks/prometheus?api-key={{ $apiKey }}'
|
||||
send_resolved: false
|
||||
{{- if $emailEnabled }}
|
||||
- name: email
|
||||
email_configs:
|
||||
- to: {{ $email.to | quote }}
|
||||
from: {{ $email.from | quote }}
|
||||
smarthost: {{ $email.smarthost | quote }}
|
||||
{{- if $email.authUsername }}
|
||||
auth_username: {{ $email.authUsername | quote }}
|
||||
auth_password_file: {{ printf "/etc/vm/secrets/%s/password" $emailPasswordSecret | quote }}
|
||||
{{- end }}
|
||||
send_resolved: true
|
||||
{{- end }}
|
||||
---
|
||||
apiVersion: operator.victoriametrics.com/v1beta1
|
||||
kind: VMAlertmanager
|
||||
@@ -284,6 +421,10 @@ spec:
|
||||
apps.cozystack.io/application.name: {{ $.Release.Name }}
|
||||
replicaCount: 3
|
||||
configSecret: alertmanager
|
||||
{{- if and $emailEnabled $email.authUsername }}
|
||||
secrets:
|
||||
- {{ $emailPasswordSecret | quote }}
|
||||
{{- end }}
|
||||
podMetadata:
|
||||
labels:
|
||||
policy.cozystack.io/allow-to-apiserver: "true"
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,228 @@
|
||||
suite: Alertmanager email input boundaries
|
||||
templates:
|
||||
- templates/alerta/alerta.yaml
|
||||
release:
|
||||
name: monitoring
|
||||
namespace: tenant-root
|
||||
set:
|
||||
_cluster.root-host: example.org
|
||||
_namespace.host: tenant-root.example.org
|
||||
_namespace.ingress: tenant-root
|
||||
alerta.alerts.email.to: oncall@example.org
|
||||
alerta.alerts.email.from: alerts@example.org
|
||||
alerta.alerts.email.smarthost: smtp.example.org:465
|
||||
tests:
|
||||
- it: "rejects malformed bracketed smarthost [deadbeef]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[deadbeef]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[deadbeef]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [...]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[...]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[...]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [1:2:3:4:5:6:7:8:9]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[1:2:3:4:5:6:7:8:9]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[1:2:3:4:5:6:7:8:9]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [1::2::3]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[1::2::3]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[1::2::3]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [1:2:3:4:5:6:7:8::]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[1:2:3:4:5:6:7:8::]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[1:2:3:4:5:6:7:8::]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [1:2:3:4::5:6:7:8]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[1:2:3:4::5:6:7:8]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[1:2:3:4::5:6:7:8]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [::ffff:256.0.0.1]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[::ffff:256.0.0.1]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[::ffff:256.0.0.1]:25\""
|
||||
|
||||
- it: "rejects malformed bracketed smarthost [192.0.2.256]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[192.0.2.256]:25"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost must be host:port, such as smtp.example.com:587, got \"[192.0.2.256]:25\""
|
||||
|
||||
- it: "rejects a leading zero in the SMTP port smtp.example.org:0465"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "smtp.example.org:0465"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost port must not contain leading zeros, got \"smtp.example.org:0465\""
|
||||
|
||||
- it: "rejects a leading zero in the SMTP port [::1]:00025"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[::1]:00025"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.smarthost port must not contain leading zeros, got \"[::1]:00025\""
|
||||
|
||||
- it: "accepts IP smarthost [::]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[::]:25"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "smarthost: \"\\[::\\]:25\""
|
||||
|
||||
- it: "accepts IP smarthost [2001:db8:0:1:2:3:4:5]:587"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[2001:db8:0:1:2:3:4:5]:587"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "smarthost: \"\\[2001:db8:0:1:2:3:4:5\\]:587\""
|
||||
|
||||
- it: "accepts IP smarthost [::ffff:192.0.2.1]:465"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[::ffff:192.0.2.1]:465"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "smarthost: \"\\[::ffff:192\\.0\\.2\\.1\\]:465\""
|
||||
|
||||
- it: "accepts IP smarthost [1:2:3:4:5:6:192.0.2.1]:587"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[1:2:3:4:5:6:192.0.2.1]:587"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "smarthost: \"\\[1:2:3:4:5:6:192\\.0\\.2\\.1\\]:587\""
|
||||
|
||||
- it: "accepts IP smarthost [192.0.2.1]:25"
|
||||
set:
|
||||
alerta.alerts.email.smarthost: "[192.0.2.1]:25"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "smarthost: \"\\[192\\.0\\.2\\.1\\]:25\""
|
||||
|
||||
- it: "accepts repeat interval 100000000ms"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "100000000ms"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "repeat_interval: \"100000000ms\""
|
||||
|
||||
- it: "accepts repeat interval 9223372036854ms"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9223372036854ms"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "repeat_interval: \"9223372036854ms\""
|
||||
|
||||
- it: "accepts repeat interval 9223372036s854ms"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9223372036s854ms"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "repeat_interval: \"9223372036s854ms\""
|
||||
|
||||
- it: "accepts repeat interval 000000000000000000000005m"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "000000000000000000000005m"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "repeat_interval: \"000000000000000000000005m\""
|
||||
|
||||
- it: "accepts repeat interval 30s"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "30s"
|
||||
asserts:
|
||||
- documentSelector:
|
||||
path: metadata.labels.app
|
||||
value: alertmanager
|
||||
matchRegex:
|
||||
path: stringData["alertmanager.yaml"]
|
||||
pattern: "repeat_interval: \"30s\""
|
||||
|
||||
- it: "rejects overflowing repeat interval 9223372036855ms"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9223372036855ms"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.repeatInterval is out of range for Alertmanager, got \"9223372036855ms\""
|
||||
|
||||
- it: "rejects overflowing repeat interval 9223372036s855ms"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9223372036s855ms"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.repeatInterval is out of range for Alertmanager, got \"9223372036s855ms\""
|
||||
|
||||
- it: "rejects overflowing repeat interval 9999999999999999999999999999999999y"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9999999999999999999999999999999999y"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.repeatInterval is out of range for Alertmanager, got \"9999999999999999999999999999999999y\""
|
||||
|
||||
- it: "rejects overflowing repeat interval 9223372036854h"
|
||||
set:
|
||||
alerta.alerts.email.repeatInterval: "9223372036854h"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.repeatInterval is out of range for Alertmanager, got \"9223372036854h\""
|
||||
|
||||
- it: "reports a whitespace-only recipient"
|
||||
set:
|
||||
alerta.alerts.email.to: " "
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "alerta.alerts.email.to has an empty entry, got \" \""
|
||||
@@ -86,6 +86,14 @@ alerta:
|
||||
disabledSeverity: []
|
||||
dashboardUrl: ""
|
||||
summaryFmt: ""
|
||||
email:
|
||||
to: ""
|
||||
from: ""
|
||||
smarthost: ""
|
||||
authUsername: ""
|
||||
repeatInterval: ""
|
||||
alertnames: []
|
||||
severities: []
|
||||
grafana:
|
||||
# Upstream Grafana image, pinned by digest and routed through
|
||||
# cozy-lib.image (so mirrored-registry installs work). Plugins (VictoriaLogs
|
||||
|
||||
Reference in new issue
Block a user