From 3cf5f41603f5644767e1089835b5e5ada513329a Mon Sep 17 00:00:00 2001 From: Shahar Glazner Date: Wed, 23 Oct 2024 14:00:10 +0300 Subject: [PATCH 01/12] fix(migrations): sqlite migration (#2275) --- .../versions/2024-10-22-10-38_8438f041ee0e.py | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py b/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py index eae0abfc5..df34c53e8 100644 --- a/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py +++ b/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py @@ -1,9 +1,7 @@ """add pulling_enabled - Revision ID: 8438f041ee0e Revises: 83c1020be97d Create Date: 2024-10-22 10:38:29.857284 - """ import sqlalchemy as sa @@ -16,13 +14,41 @@ depends_on = None +def is_sqlite(): + """Check if we're running on SQLite""" + bind = op.get_bind() + return bind.engine.name == "sqlite" + + def upgrade() -> None: # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table("provider", schema=None) as batch_op: - batch_op.add_column( - sa.Column("pulling_enabled", sa.Boolean(), nullable=False, default=True) - ) - # ### end Alembic commands ### + if is_sqlite(): + # SQLite specific implementation + with op.batch_alter_table("provider", schema=None) as batch_op: + # First add the column as nullable with a default value + batch_op.add_column( + sa.Column( + "pulling_enabled", + sa.Boolean(), + server_default=sa.true(), + nullable=True, + ) + ) + + # Then make it not nullable if needed + with op.batch_alter_table("provider", schema=None) as batch_op: + batch_op.alter_column("pulling_enabled", nullable=False) + else: + # Implementation for other databases + with op.batch_alter_table("provider", schema=None) as batch_op: + batch_op.add_column( + sa.Column( + "pulling_enabled", + sa.Boolean(), + nullable=False, + server_default=sa.true(), + ) + ) def downgrade() -> None: From 124550e1b9ceaf930d6d6c094f6a8fa36e916ddf Mon Sep 17 00:00:00 2001 From: shahargl Date: Wed, 23 Oct 2024 14:00:59 +0300 Subject: [PATCH 02/12] fix: sqlite migration --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5546b50e7..e7101468b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.27.1" +version = "0.27.2" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md" From 335e843611b8d8c7855c33638ba39df532a3cc2e Mon Sep 17 00:00:00 2001 From: Shahar Glazner Date: Wed, 23 Oct 2024 15:11:41 +0300 Subject: [PATCH 03/12] fix(migrations): db's other than sqlite (#2276) --- .../versions/2024-10-22-10-38_8438f041ee0e.py | 27 ++++++++++++------- pyproject.toml | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py b/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py index df34c53e8..dac33f5aa 100644 --- a/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py +++ b/keep/api/models/db/migrations/versions/2024-10-22-10-38_8438f041ee0e.py @@ -39,16 +39,23 @@ def upgrade() -> None: with op.batch_alter_table("provider", schema=None) as batch_op: batch_op.alter_column("pulling_enabled", nullable=False) else: - # Implementation for other databases - with op.batch_alter_table("provider", schema=None) as batch_op: - batch_op.add_column( - sa.Column( - "pulling_enabled", - sa.Boolean(), - nullable=False, - server_default=sa.true(), - ) - ) + # PostgreSQL and other databases implementation + # 1. Add the column as nullable + op.add_column( + "provider", sa.Column("pulling_enabled", sa.Boolean(), nullable=True) + ) + # 2. Set default value for existing rows + op.execute( + "UPDATE provider SET pulling_enabled = true WHERE pulling_enabled IS NULL" + ) + # 3. Make it non-nullable with default + op.alter_column( + "provider", + "pulling_enabled", + existing_type=sa.Boolean(), + nullable=False, + server_default=sa.true(), + ) def downgrade() -> None: diff --git a/pyproject.toml b/pyproject.toml index e7101468b..e1de24eae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.27.2" +version = "0.27.3" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md" From 21da034b7f5704eb2f07241bfda36639fa6ab935 Mon Sep 17 00:00:00 2001 From: Tal Date: Thu, 24 Oct 2024 00:17:27 +0300 Subject: [PATCH 04/12] fix(zabbix): add ipaddress and hostname (#2279) --- keep/providers/zabbix_provider/zabbix_provider.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/keep/providers/zabbix_provider/zabbix_provider.py b/keep/providers/zabbix_provider/zabbix_provider.py index b7bca0ad3..9ca8d7b14 100644 --- a/keep/providers/zabbix_provider/zabbix_provider.py +++ b/keep/providers/zabbix_provider/zabbix_provider.py @@ -594,6 +594,8 @@ def _format_alert( event_id = event.get("id") trigger_id = event.get("triggerId") zabbix_url = event.pop("ZABBIX.URL", None) + hostname = event.get("HOST.NAME") + ip_address = event.get("HOST.IP") if zabbix_url == "{$ZABBIX.URL}": # This means user did not configure $ZABBIX.URL in Zabbix probably @@ -638,6 +640,9 @@ def _format_alert( url=url, lastReceived=last_received, tags=tags, + hostname=hostname, + service=hostname, + ip_address=ip_address, ) From 580b5673f0cc4d7f678639580faba0820e58a373 Mon Sep 17 00:00:00 2001 From: Tal Date: Thu, 24 Oct 2024 09:47:03 +0300 Subject: [PATCH 05/12] chore(version): bump version to 0.27.4 (#2281) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e1de24eae..364b6b2f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.27.3" +version = "0.27.4" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md" From 28df747b8bb75ce240425dcdcd2310dd17d0c38e Mon Sep 17 00:00:00 2001 From: Shahar Glazner Date: Thu, 24 Oct 2024 16:28:18 +0300 Subject: [PATCH 06/12] fix: workflow last run time (#2286) --- examples/workflows/cron-digest-alerts.yml | 15 +++++---- keep/contextmanager/contextmanager.py | 3 ++ keep/providers/keep_provider/keep_provider.py | 31 +++++++++++++++++++ pyproject.toml | 2 +- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/examples/workflows/cron-digest-alerts.yml b/examples/workflows/cron-digest-alerts.yml index 10baa9ecc..a4bcd786b 100644 --- a/examples/workflows/cron-digest-alerts.yml +++ b/examples/workflows/cron-digest-alerts.yml @@ -2,6 +2,7 @@ workflow: id: alerts-daily-digest description: run alerts digest twice a day (on 11:00 and 14:00) triggers: + - type: manual - type: interval cron: 0 11,14 * * * steps: @@ -10,18 +11,16 @@ workflow: provider: type: keep with: - filters: - # filter out alerts that are closed - - key: status - value: open + version: 2 + filter: "status == 'firing'" timerange: - from: "{{ state.workflows.alerts-daily-digest.last_run_time }}" + from: "{{ last_workflow_run_time }}" to: now actions: - name: send-digest foreach: "{{ steps.get-alerts.results }}" provider: - type: slack - config: "{{ providers.slack }}" + type: console + config: "{{ providers.console }}" with: - message: "Open alert: {{ foreach.value.name }}" + message: "Open alerts: {{ foreach.value.name }}" diff --git a/keep/contextmanager/contextmanager.py b/keep/contextmanager/contextmanager.py index b044962c4..59ca134bc 100644 --- a/keep/contextmanager/contextmanager.py +++ b/keep/contextmanager/contextmanager.py @@ -35,6 +35,7 @@ def __init__(self, tenant_id, workflow_id=None, workflow_execution_id=None): self.click_context = {} # last workflow context self.last_workflow_execution_results = {} + self.last_workflow_run_time = None if self.workflow_id: try: last_workflow_execution = get_last_workflow_execution_by_workflow_id( @@ -44,6 +45,7 @@ def __init__(self, tenant_id, workflow_id=None, workflow_execution_id=None): self.last_workflow_execution_results = ( last_workflow_execution.results ) + self.last_workflow_run_time = last_workflow_execution.started except Exception: self.logger.exception("Failed to get last workflow execution") pass @@ -130,6 +132,7 @@ def get_full_context(self, exclude_providers=False, exclude_env=False): "foreach": self.foreach_context, "event": self.event_context, "last_workflow_results": self.last_workflow_execution_results, + "last_workflow_run_time": self.last_workflow_run_time, "alert": self.event_context, # this is an alias so workflows will be able to use alert.source "incident": self.incident_context, # this is an alias so workflows will be able to use alert.source "consts": self.consts_context, diff --git a/keep/providers/keep_provider/keep_provider.py b/keep/providers/keep_provider/keep_provider.py index c06f251f0..6a7137b59 100644 --- a/keep/providers/keep_provider/keep_provider.py +++ b/keep/providers/keep_provider/keep_provider.py @@ -3,6 +3,7 @@ """ import logging +from datetime import datetime, timezone from keep.api.core.db import get_alerts_with_filters from keep.api.models.alert import AlertDto @@ -28,6 +29,31 @@ def dispose(self): """ pass + def _calculate_time_delta(self, timerange=None, default_time_range=1): + """Calculate time delta in days from timerange dict.""" + if not timerange or "from" not in timerange: + return default_time_range # default value + + from_time_str = timerange["from"] + to_time_str = timerange.get("to", "now") + + # Parse from_time and ensure it's timezone-aware + from_time = datetime.fromisoformat(from_time_str.replace("Z", "+00:00")) + if from_time.tzinfo is None: + from_time = from_time.replace(tzinfo=timezone.utc) + + # Handle 'to' time + if to_time_str == "now": + to_time = datetime.now(timezone.utc) + else: + to_time = datetime.fromisoformat(to_time_str.replace("Z", "+00:00")) + if to_time.tzinfo is None: + to_time = to_time.replace(tzinfo=timezone.utc) + + # Calculate difference in days + delta = (to_time - from_time).total_seconds() / (24 * 3600) # convert to days + return delta + def _query(self, filters=None, version=1, distinct=True, time_delta=1, **kwargs): """ Query Keep for alerts. @@ -40,6 +66,11 @@ def _query(self, filters=None, version=1, distinct=True, time_delta=1, **kwargs) "time_delta": time_delta, }, ) + # if timerange is provided, calculate time delta + if kwargs.get("timerange"): + time_delta = self._calculate_time_delta( + timerange=kwargs.get("timerange"), default_time_range=time_delta + ) if version == 1: # filters are mandatory for version 1 if not filters: diff --git a/pyproject.toml b/pyproject.toml index 364b6b2f3..1898f83fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.27.4" +version = "0.27.5" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md" From 72557372a0fac11ee814048d7bee73a943605405 Mon Sep 17 00:00:00 2001 From: Rutam Prita Mishra Date: Thu, 24 Oct 2024 20:56:12 +0530 Subject: [PATCH 07/12] docs: Fix typos on multiple pages of Keep Docs Site (#2288) --- docs/deployment/configuration.mdx | 2 +- docs/deployment/ecs.mdx | 2 +- docs/deployment/stress-testing.mdx | 2 +- docs/overview/comparisons.mdx | 2 +- docs/overview/deduplication.mdx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/deployment/configuration.mdx b/docs/deployment/configuration.mdx index f4c1a1714..abcbb00fc 100644 --- a/docs/deployment/configuration.mdx +++ b/docs/deployment/configuration.mdx @@ -69,7 +69,7 @@ Resource provisioning settings control how Keep sets up initial resources. This Authentication configuration determines how Keep verifies user identities and manages access control. These settings are essential for securing your Keep instance and integrating with various authentication providers. -For specifc authentication type configuration, please see [authentication docs](/deployment/authentication/overview). +For specific authentication type configuration, please see [authentication docs](/deployment/authentication/overview). | Env var | Purpose | Required | Default Value | Valid options | diff --git a/docs/deployment/ecs.mdx b/docs/deployment/ecs.mdx index 097092e1a..61289afcd 100644 --- a/docs/deployment/ecs.mdx +++ b/docs/deployment/ecs.mdx @@ -102,7 +102,7 @@ sidebarTitle: "AWS ECS" - Configuration Type: Configure at task definition creation - Volume type: EFS - Storage configurations: - - File system ID: Select an exisiting EFS filesystem or create a new one + - File system ID: Select an existing EFS filesystem or create a new one - Root Directory: / ![Volume Configuration](/images/ecs-task-def-backend5.png) - Container mount points: diff --git a/docs/deployment/stress-testing.mdx b/docs/deployment/stress-testing.mdx index 9f9dc9716..14ebb48c2 100644 --- a/docs/deployment/stress-testing.mdx +++ b/docs/deployment/stress-testing.mdx @@ -27,7 +27,7 @@ The primary parameters that affect the specification requirements for Keep are: 3. **Number of Workflows**: How many automation run as a result of alert. ### Main Components: -- **Keep Backend** - API and buisness logic. A container that serves FastAPI on top of gunicorn. +- **Keep Backend** - API and business logic. A container that serves FastAPI on top of gunicorn. - **Keep Frontend** - Web app. A container that serves the react app. - **Database** - Stores the alerts and any other operational data. - **Elasticsearch** (opt out by default) - Stores alerts as document for better search performance. diff --git a/docs/overview/comparisons.mdx b/docs/overview/comparisons.mdx index 2329579f3..e26f70623 100644 --- a/docs/overview/comparisons.mdx +++ b/docs/overview/comparisons.mdx @@ -17,7 +17,7 @@ Keep is different because it’s able to correlate alerts between different obse | | Keep | Alternative | | ------------------------------------- | -------------------------------------------------------------- | ---------------------------- | | Aggregates alerts from one platform | ✅ | ✅ | -| Aggregates alerts from mutliple platforms | ✅ | ❌ | +| Aggregates alerts from multiple platforms | ✅ | ❌ | | Correlates alerts between multiple sources | ✅ | ❌ | | Alerts enrichment | ✅ | ❌ | | Open source | ✅ | ❌ | diff --git a/docs/overview/deduplication.mdx b/docs/overview/deduplication.mdx index 00d755ec5..a0e3eabb6 100644 --- a/docs/overview/deduplication.mdx +++ b/docs/overview/deduplication.mdx @@ -20,7 +20,7 @@ Alert deduplication is a crucial feature in Keep that helps reduce noise and str Partial deduplication allows you to specify certain fields (fingerprint fields) that are used to identify similar alerts. Alerts with matching values in these specified fields are considered duplicates and are grouped together. This method is flexible and allows for fine-tuned control over how alerts are deduplicated. Every provider integrated with Keep comes with pre-built partial deduplication rule tailored to that provider's specific alert format and common use cases. -The default fingerprint fields defined using `FINGERPRINT_FIELDS` attributes in the provider code (e.g. [datadog provider](https://github.com/keephq/keep/blob/main/keep/providers/datadog_provider/datadog_provider.py#L188) or [gcp monitoring provder](https://github.com/keephq/keep/blob/main/keep/providers/gcpmonitoring_provider/gcpmonitoring_provider.py#L52)). +The default fingerprint fields defined using `FINGERPRINT_FIELDS` attributes in the provider code (e.g. [datadog provider](https://github.com/keephq/keep/blob/main/keep/providers/datadog_provider/datadog_provider.py#L188) or [gcp monitoring provider](https://github.com/keephq/keep/blob/main/keep/providers/gcpmonitoring_provider/gcpmonitoring_provider.py#L52)). ### Full Deduplication When full deduplication is enabled, Keep will also discard exact same events (excluding ignore fields). This mode considers all fields of an alert when determining duplicates, except for explicitly ignored fields. From 7290eb03d7888e21fda1e967aa58453311b0b5b3 Mon Sep 17 00:00:00 2001 From: Shahar Glazner Date: Thu, 24 Oct 2024 19:33:18 +0300 Subject: [PATCH 08/12] fix(ui): incident add a comment uses old API (#2291) --- keep-ui/app/incidents/[id]/incident-activity.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/keep-ui/app/incidents/[id]/incident-activity.tsx b/keep-ui/app/incidents/[id]/incident-activity.tsx index 2ab11e50f..9cdf91f26 100644 --- a/keep-ui/app/incidents/[id]/incident-activity.tsx +++ b/keep-ui/app/incidents/[id]/incident-activity.tsx @@ -15,7 +15,7 @@ import { import { AuditEvent, useAlerts } from "@/utils/hooks/useAlerts"; import Loading from "@/app/loading"; import { useCallback, useState, useEffect } from "react"; -import { getApiURL } from "@/utils/apiUrl"; +import { useApiUrl } from "@/utils/hooks/useConfig"; import { useSession } from "next-auth/react"; import { KeyedMutator } from "swr"; import { toast } from "react-toastify"; @@ -59,7 +59,6 @@ export function IncidentActivityChronoItem({ activity }: { activity: any }) { ); } - export function IncidentActivityChronoItemComment({ incident, mutator, @@ -68,7 +67,7 @@ export function IncidentActivityChronoItemComment({ mutator: KeyedMutator; }) { const [comment, setComment] = useState(""); - const apiUrl = getApiURL(); + const apiUrl = useApiUrl(); const { data: session } = useSession(); const onSubmit = useCallback(async () => { From 05740670747f0a6a8c36151451d04c4c4d08ca37 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 24 Oct 2024 18:41:22 +0200 Subject: [PATCH 09/12] fix: alert enriching is always disposable (no matter query params) (#2293) Co-authored-by: Tal Borenstein --- keep/api/routes/alerts.py | 43 +++++++++++++++++++++++---------------- pyproject.toml | 2 +- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/keep/api/routes/alerts.py b/keep/api/routes/alerts.py index c14c092f9..8a35b8f9d 100644 --- a/keep/api/routes/alerts.py +++ b/keep/api/routes/alerts.py @@ -4,7 +4,7 @@ import json import logging import os -from typing import Optional, List +from typing import List, Optional import celpy from arq import ArqRedis @@ -25,7 +25,12 @@ from keep.api.consts import KEEP_ARQ_QUEUE_BASIC from keep.api.core.config import config from keep.api.core.db import get_alert_audit as get_alert_audit_db -from keep.api.core.db import get_alerts_by_fingerprint, get_enrichment, get_last_alerts, get_alerts_metrics_by_provider +from keep.api.core.db import ( + get_alerts_by_fingerprint, + get_alerts_metrics_by_provider, + get_enrichment, + get_last_alerts, +) from keep.api.core.dependencies import extract_generic_body, get_pusher_client from keep.api.core.elastic import ElasticClient from keep.api.models.alert import ( @@ -37,15 +42,15 @@ from keep.api.models.alert_audit import AlertAuditDto from keep.api.models.db.alert import AlertActionType from keep.api.models.search_alert import SearchAlertsRequest +from keep.api.models.time_stamp import TimeStampFilter from keep.api.tasks.process_event_task import process_event from keep.api.utils.email_utils import EmailTemplates, send_email from keep.api.utils.enrichment_helpers import convert_db_alerts_to_dto_alerts +from keep.api.utils.time_stamp_helpers import get_time_stamp_filter from keep.identitymanager.authenticatedentity import AuthenticatedEntity from keep.identitymanager.identitymanagerfactory import IdentityManagerFactory from keep.providers.providers_factory import ProvidersFactory from keep.searchengine.searchengine import SearchEngine -from keep.api.utils.time_stamp_helpers import get_time_stamp_filter -from keep.api.models.time_stamp import TimeStampFilter router = APIRouter() logger = logging.getLogger(__name__) @@ -447,19 +452,23 @@ def enrich_alert( authenticated_entity: AuthenticatedEntity = Depends( IdentityManagerFactory.get_auth_verifier(["write:alert"]) ), + dispose_on_new_alert: Optional[bool] = Query( + False, description="Dispose on new alert" + ), ) -> dict[str, str]: - return _enrich_alert(enrich_data, authenticated_entity=authenticated_entity) + return _enrich_alert( + enrich_data, + authenticated_entity=authenticated_entity, + dispose_on_new_alert=dispose_on_new_alert, + ) def _enrich_alert( enrich_data: EnrichAlertRequestBody, - pusher_client: Pusher = Depends(get_pusher_client), authenticated_entity: AuthenticatedEntity = Depends( IdentityManagerFactory.get_auth_verifier(["write:alert"]) ), - dispose_on_new_alert: Optional[bool] = Query( - False, description="Dispose on new alert" - ), + dispose_on_new_alert: Optional[bool] = False, ) -> dict[str, str]: tenant_id = authenticated_entity.tenant_id logger.info( @@ -469,7 +478,6 @@ def _enrich_alert( "tenant_id": tenant_id, }, ) - try: enrichement_bl = EnrichmentsBl(tenant_id) # Shahar: TODO, change to the specific action type, good enough for now @@ -530,6 +538,7 @@ def _enrich_alert( logger.exception("Failed to push alert to elasticsearch") pass # use pusher to push the enriched alert to the client + pusher_client = get_pusher_client() if pusher_client: logger.info("Telling client to poll alerts") try: @@ -770,17 +779,15 @@ def get_alert_quality( ): logger.info( "Fetching alert quality metrics per provider", - extra={ - "tenant_id": authenticated_entity.tenant_id, - "fields": fields - }, - + extra={"tenant_id": authenticated_entity.tenant_id, "fields": fields}, ) start_date = time_stamp.lower_timestamp if time_stamp else None end_date = time_stamp.upper_timestamp if time_stamp else None db_alerts_quality = get_alerts_metrics_by_provider( - tenant_id=authenticated_entity.tenant_id, start_date=start_date, end_date=end_date, - fields=fields + tenant_id=authenticated_entity.tenant_id, + start_date=start_date, + end_date=end_date, + fields=fields, ) - + return db_alerts_quality diff --git a/pyproject.toml b/pyproject.toml index 1898f83fc..6d44fbede 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.27.5" +version = "0.27.6" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md" From 2eee661074d098c58befe3b2810f2637969b64f0 Mon Sep 17 00:00:00 2001 From: Shahar Glazner Date: Fri, 25 Oct 2024 15:12:20 +0300 Subject: [PATCH 10/12] docs(k8s): read environment variable from secret (#2300) --- docs/deployment/kubernetes/overview.mdx | 1 + docs/deployment/secret-manager.mdx | 85 ++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/docs/deployment/kubernetes/overview.mdx b/docs/deployment/kubernetes/overview.mdx index b40d9c771..a3d889f07 100644 --- a/docs/deployment/kubernetes/overview.mdx +++ b/docs/deployment/kubernetes/overview.mdx @@ -14,5 +14,6 @@ We maintain an opinionated, batteries-included Helm chart, but you can customize ## Next steps - Install Keep on [Kubernetes](/deployment/kubernetes/installation). - Keep's [Helm Chart](https://github.com/keephq/helm-charts). +- Keep with [Kubernetes Secret Manager](/deployment/secret-manager#kubernetes-secret-manager) - Deep dive to Keep's kubernetes [Architecture](/deployment/kubernetes/architecture). - Install Keep on [OpenShift](/deployment/kubernetes/openshift). diff --git a/docs/deployment/secret-manager.mdx b/docs/deployment/secret-manager.mdx index e6db52f51..00b18cb3b 100644 --- a/docs/deployment/secret-manager.mdx +++ b/docs/deployment/secret-manager.mdx @@ -59,11 +59,16 @@ Usage: ## Kubernetes Secret Manager -The `KubernetesSecretManager` interfaces with Kubernetes' native secrets system. It manages secrets within a specified Kubernetes namespace and is designed to operate within a Kubernetes cluster. +### Overview -Configuration: +The `KubernetesSecretManager` interfaces with Kubernetes' native secrets system. + +It manages secrets within a specified Kubernetes namespace and is designed to operate within a Kubernetes cluster. + +### Configuration -Set `K8S_NAMESPACE` environment variable to specify the Kubernetes namespace. Defaults to default if not set. Assumes Kubernetes configurations (like service account tokens) are properly set up when running within a cluster. +- `SECRET_MANAGER_TYPE=k8s` +- `K8S_NAMESPACE=keep` - environment variable to specify the Kubernetes namespace. Defaults to `.metadata.namespace` if not set. Assumes Kubernetes configurations (like service account tokens) are properly set up when running within a cluster. Usage: @@ -71,6 +76,80 @@ Usage: - Provides functionalities to create, retrieve, and delete Kubernetes secrets. - Handles base64 encoding and decoding as required by Kubernetes. +### Environment Variables From Secrets +The Kubernetes Secret Manager integration allows Keep to fetch environment variables from Kubernetes Secrets. + +For sensitive environment variables, such as `DATABASE_CONNECTION_STRING`, it is recommended to store as a secret: + +#### Creating Database Connection Secret +```bash +# Create the base64 encoded string without newline +CONNECTION_STRING_B64=$(echo -n "mysql+pymysql://user:password@host:3306/dbname" | base64) + +# Create the Kubernetes secret +kubectl create secret generic keep-db-secret \ + --namespace=keep \ + --from-literal=connection_string=$(echo -n "mysql+pymysql://user:password@host:3306/dbname" | base64) + +# Or using a YAML file: +cat < Date: Fri, 25 Oct 2024 18:58:43 +0300 Subject: [PATCH 11/12] docs: better docs on ingress (#2304) --- docs/deployment/kubernetes/installation.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/deployment/kubernetes/installation.mdx b/docs/deployment/kubernetes/installation.mdx index 5b3010ffd..9680df532 100644 --- a/docs/deployment/kubernetes/installation.mdx +++ b/docs/deployment/kubernetes/installation.mdx @@ -46,8 +46,11 @@ To read about more installation options, see [ingress-nginx installation docs](h ```bash # simplest way to install +# we set snippet-annotations to true to allow rewrites +# see https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#allow-snippet-annotations helm upgrade --install ingress-nginx ingress-nginx \ --repo https://kubernetes.github.io/ingress-nginx \ + --set controller.config.allow-snippet-annotations=true \ --namespace ingress-nginx --create-namespace ``` From 519ab28c6fd9c3f12f2aab578e7d065007c4d2ce Mon Sep 17 00:00:00 2001 From: Rutam Prita Mishra Date: Sun, 27 Oct 2024 12:48:07 +0530 Subject: [PATCH 12/12] docs: Fix typos on certain pages of Keep Docs Site (#2295) --- docs/overview/examples.mdx | 6 +++--- docs/overview/introduction.mdx | 2 +- docs/overview/keyconcepts.mdx | 2 +- docs/providers/adding-a-new-provider.mdx | 8 ++++---- docs/providers/documentation/auth0-provider.mdx | 2 +- docs/workflows/state.mdx | 4 ++-- docs/workflows/syntax/basic-syntax.mdx | 6 +++--- docs/workflows/syntax/context-syntax.mdx | 4 ++-- docs/workflows/syntax/foreach-syntax.mdx | 2 +- docs/workflows/throttles/one-until-resolved.mdx | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/overview/examples.mdx b/docs/overview/examples.mdx index 69ae876c1..fc81bf413 100644 --- a/docs/overview/examples.mdx +++ b/docs/overview/examples.mdx @@ -6,10 +6,10 @@ title: "Examples" ## Create an incident only if the customer is on Enterprise tier -In this example we will utilze: +In this example we will utilize: 1. Datadog for monitoring -2. OpsGenie for incident managment +2. OpsGenie for incident management 3. A postgres database that stores the customer tier. This example consists of two steps: @@ -45,7 +45,7 @@ alert: type: opsgenie config: " {{ providers.opsgenie-prod }} " with: - message: "A new alert on enteprise customer ( {{ steps.check-if-customer-is-enterprise.results[1] }} )" + message: "A new alert on enterprise customer ( {{ steps.check-if-customer-is-enterprise.results[1] }} )" ``` ## Send a slack message for every Cloudwatch alarm diff --git a/docs/overview/introduction.mdx b/docs/overview/introduction.mdx index b52681e87..e873e9654 100644 --- a/docs/overview/introduction.mdx +++ b/docs/overview/introduction.mdx @@ -1,6 +1,6 @@ --- title: "Introduction" -description: "Keep is an open-source alert management and automation tool that provides everything you need to collect, enrich and manange alerts effectively." +description: "Keep is an open-source alert management and automation tool that provides everything you need to collect, enrich and manage alerts effectively." --- You can start using Keep by logging in to the [platform](https://platform.keephq.dev). diff --git a/docs/overview/keyconcepts.mdx b/docs/overview/keyconcepts.mdx index 07c2193fe..77cd21758 100644 --- a/docs/overview/keyconcepts.mdx +++ b/docs/overview/keyconcepts.mdx @@ -23,7 +23,7 @@ A Provider can either push alerts into Keep, or Keep can pull alerts from the Pr #### Push alerts to Keep (Manual) You can configure your alert source to push alerts into Keep. -For example, consider Promethues. If you want to push alerts from Promethues to Keep, you'll need to configure Promethues Alertmanager to send the alerts to +For example, consider Prometheus. If you want to push alerts from Prometheus to Keep, you'll need to configure Prometheus Alertmanager to send the alerts to 'https://api.keephq.dev/alerts/event/prometheus' using API key authentication. Each Provider implements Push mechanism and is documented under the specific Provider page. #### Push alerts to Keep (Automatic) diff --git a/docs/providers/adding-a-new-provider.mdx b/docs/providers/adding-a-new-provider.mdx index d81520cda..e2541e95b 100644 --- a/docs/providers/adding-a-new-provider.mdx +++ b/docs/providers/adding-a-new-provider.mdx @@ -2,7 +2,7 @@ title: "Adding a new Provider" sidebarTitle: "Adding a New Provider" --- -Under contstruction +Under construction ### Basics @@ -192,7 +192,7 @@ class BaseProvider(metaclass=abc.ABCMeta): ) # else, if we are in an event context, use the event fingerprint elif self.context_manager.event_context: - # TODO: map all casses event_context is dict and update them to the DTO + # TODO: map all cases event_context is dict and update them to the DTO # and remove this if statement if isinstance(self.context_manager.event_context, dict): fingerprint = self.context_manager.event_context.get("fingerprint") @@ -446,7 +446,7 @@ class BaseProvider(metaclass=abc.ABCMeta): @staticmethod def parse_event_raw_body(raw_body: bytes) -> bytes: """ - Parse the raw body of an event and create an ingestable dict from it. + Parse the raw body of an event and create an ingestible dict from it. For instance, in parseable, the "event" is just a string > b'Alert: Server side error triggered on teststream1\nMessage: server reporting status as 500\nFailing Condition: status column equal to abcd, 2 times' @@ -459,7 +459,7 @@ class BaseProvider(metaclass=abc.ABCMeta): raw_body (bytes): The raw body of the incoming event (/event endpoint in alerts.py) Returns: - dict: Ingestable event + dict: Ingestible event """ return raw_body diff --git a/docs/providers/documentation/auth0-provider.mdx b/docs/providers/documentation/auth0-provider.mdx index 8eb53bc4e..0ea5aa8b0 100644 --- a/docs/providers/documentation/auth0-provider.mdx +++ b/docs/providers/documentation/auth0-provider.mdx @@ -51,6 +51,6 @@ workflow: audience: "https://api.example.com" grant_type: "client_credentials" -##Usefull Links +## Useful Links -[Auth0 API Documentation](https://auth0.com/docs/api) -[Auth0 as an authentication method for keep](https://docs.keephq.dev/deployment/authentication/auth0-auth) \ No newline at end of file diff --git a/docs/workflows/state.mdx b/docs/workflows/state.mdx index c06e46f34..3ef54c15d 100644 --- a/docs/workflows/state.mdx +++ b/docs/workflows/state.mdx @@ -8,7 +8,7 @@ Keep State Manager is currently used for: 2. Track alerts over time 3. Previous runs context -State is currently being saved as a JSON file under `./state/keepstate.json`, a path that can be overriden by setting the `KEEP_STATE_FILE` environment variable. +State is currently being saved as a JSON file under `./state/keepstate.json`, a path that can be overridden by setting the `KEEP_STATE_FILE` environment variable. ## Example One of the usages for Keep's state mechanism is throttling, see [One Until Resolved](/workflows/throttles/one-until-resolved) Keep handles it for you behind the scenes so you can use it without doing any further modifications. @@ -44,4 +44,4 @@ An example for a simple state file: Keep's roadmap around state (great first issues): - Saving state in a database. - Hosting state in buckets (AWS, GCP and Azure -> read/write). -- Enriching state with more context so throttling mechanism would be flexer. +- Enriching state with more context so throttling mechanism would be flexible. diff --git a/docs/workflows/syntax/basic-syntax.mdx b/docs/workflows/syntax/basic-syntax.mdx index 143dff685..b7ea0f28c 100644 --- a/docs/workflows/syntax/basic-syntax.mdx +++ b/docs/workflows/syntax/basic-syntax.mdx @@ -4,7 +4,7 @@ description: "At Keep, we view alerts as workflows, which consist of a series of --- ## Full Example ```yaml title=examples/raw_sql_query_datetime.yml -# Notify if a result queried from the DB is above a certain thershold. +# Notify if a result queried from the DB is above a certain threshold. workflow: id: raw-sql-query description: Monitor that time difference is no more than 1 hour @@ -52,7 +52,7 @@ workflow: - Metadata (id, description. owners and tags will be added soon) - `steps` - list of steps - `actions` - list of actions -- `on-failure` - a conditionless action used in case of an alert failure +- `on-failure` - an action with no condition used in case of an alert failure ### Provider ```yaml @@ -126,5 +126,5 @@ on-failure: config: " {{ providers.slack-demo }} " ``` -On-failure is actually a condtionless `Action` used to notify in case the alert failed with an exception. +On-failure is actually an `Action` with no condition used to notify in case the alert failed with an exception. The provider is passed a `message` (string) to it's `notify` function. diff --git a/docs/workflows/syntax/context-syntax.mdx b/docs/workflows/syntax/context-syntax.mdx index 4cf854780..62cff7253 100644 --- a/docs/workflows/syntax/context-syntax.mdx +++ b/docs/workflows/syntax/context-syntax.mdx @@ -1,6 +1,6 @@ --- title: "Working with context" -sidebarTitle: "Content Syntax" +sidebarTitle: "Context Syntax" description: "Keep uses [Mustache](https://mustache.github.io/) syntax to inject context at runtime, supporting functions, dictionaries, lists, and nested access." --- @@ -12,7 +12,7 @@ Here are some examples: - `keep.first({{ steps.this.results }})` - First result (equivalent to the previous example) - `{{ steps.step-id.results[0][0] }}` - First item of the first result -If you have suggestions/improvments/bugs for Keep's syntax, please [open feature request](https://github.com/keephq/keep/issues/new?assignees=&labels=&template=feature_request.md&title=) and get eternal glory. +If you have suggestions/improvements/bugs for Keep's syntax, please [open feature request](https://github.com/keephq/keep/issues/new?assignees=&labels=&template=feature_request.md&title=) and get eternal glory. ### Special context diff --git a/docs/workflows/syntax/foreach-syntax.mdx b/docs/workflows/syntax/foreach-syntax.mdx index 310f7ceb0..0d8433dca 100644 --- a/docs/workflows/syntax/foreach-syntax.mdx +++ b/docs/workflows/syntax/foreach-syntax.mdx @@ -1,7 +1,7 @@ --- title: "Foreach" sidebarTitle: "Foreach Syntax" -description: "Foreach syntax add the flexability of running action per result instead of only once on all results." +description: "Foreach syntax add the flexibility of running action per result instead of only once on all results." --- ## Usage diff --git a/docs/workflows/throttles/one-until-resolved.mdx b/docs/workflows/throttles/one-until-resolved.mdx index 6f36874bd..491c0b7bc 100644 --- a/docs/workflows/throttles/one-until-resolved.mdx +++ b/docs/workflows/throttles/one-until-resolved.mdx @@ -8,7 +8,7 @@ For example: 1. Alert executed and action were triggered as a result -> the alert status is now "Firing". 2. Alert executed again and action should be triggered -> the action will be throttled. 3. Alert executed and no action is required -> the alert status is now "Resolved". -4. Alert exectued and action were triggered -> the action is triggered +4. Alert executed and action were triggered -> the action is triggered ## How to use