diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..36efbd1 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +MATTERMOST_WEBHOOK_URL= +MATTERMOST_CHANNEL= diff --git a/README.md b/README.md index 81ce4f2..2f30ca3 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ Dedicated mainly to report CNPG cluster status. ## Getting Started +Copy and edit `.env.example`. Leave empty values for mattermost if you don't want to use it. + Run the development daemon: ```bash diff --git a/package.json b/package.json index d0ef06a..bb86874 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "license": "MIT", "scripts": { "build": "tsc && tsc-alias", - "dev": "FORCE_COLOR=true tsx watch src/**/*.ts | pino-pretty", + "dev": "FORCE_COLOR=true tsx watch --env-file=.env src/**/*.ts | pino-pretty", "lint": "eslint src/**/*.ts && prettier --check src/**/*.ts", "format": "prettier --write src/**/*.ts", "postinstall": "is-ci || husky install", diff --git a/src/lib/config.ts b/src/lib/config.ts new file mode 100644 index 0000000..7421493 --- /dev/null +++ b/src/lib/config.ts @@ -0,0 +1,17 @@ +import { logger } from "./logger" + +export const MATTERMOST_WEBHOOK_URL: string | undefined = + process.env.MATTERMOST_WEBHOOK_URL +export const MATTERMOST_CHANNEL: string | undefined = + process.env.MATTERMOST_CHANNEL + +if (!MATTERMOST_WEBHOOK_URL) { + logger.info("MATTERMOST_WEBHOOK_URL not configured") +} + +if (MATTERMOST_WEBHOOK_URL && !MATTERMOST_CHANNEL) { + logger.error( + "MATTERMOST_WEBHOOK_URL is defined so MATTERMOST_CHANNEL is required" + ) + process.exit(1) +} diff --git a/src/lib/kube-watcher.ts b/src/lib/kube-watcher.ts index 013275d..c8dd1db 100644 --- a/src/lib/kube-watcher.ts +++ b/src/lib/kube-watcher.ts @@ -10,6 +10,7 @@ import { getCnpgClusterArchivingStatus, } from "@/lib/kube/types" import { logger } from "@/lib/logger" +import { sendNotification } from "@/lib/mattermost" const allContexts = ["dev", "prod", "ovh-dev", "ovh-prod"] @@ -176,13 +177,19 @@ function checkCnpgCluster( const cacheKey = JSON.stringify(status) const alertInCache = alertCache.has(cacheKey) + const mattermostFields = Object.entries(status).map(([key, value]) => { + return { title: key, value: String(value) } + }) + if (statusOk && !alertInCache) { return } else if (statusOk && alertInCache) { logger.info(status, "cnpgCluster alert resolved") + sendNotification(statusOk, "cnpgCluster alert resolved", mattermostFields) alertCache.delete(cacheKey) } else if (!statusOk && !alertInCache) { logger.error(status, "cnpgCluster alert") + sendNotification(statusOk, "cnpgCluster alert", mattermostFields) alertCache.set(cacheKey, true) } diff --git a/src/lib/mattermost.ts b/src/lib/mattermost.ts new file mode 100644 index 0000000..ef6d0ee --- /dev/null +++ b/src/lib/mattermost.ts @@ -0,0 +1,36 @@ +import { MATTERMOST_WEBHOOK_URL, MATTERMOST_CHANNEL } from "@/lib/config" +import { logger } from "@/lib/logger" + +export async function sendNotification( + status: boolean, + title: string, + fields: { title: string; value: string }[] +) { + if (!MATTERMOST_WEBHOOK_URL) { + return + } + + try { + await fetch(MATTERMOST_WEBHOOK_URL, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + channel: MATTERMOST_CHANNEL, + author_name: "kubesight-alerts", + attachments: [ + { + color: status ? "#00FF00" : "#FF0000", + title, + fields: fields.map((field) => { + return { ...field, short: true } + }), + }, + ], + }), + }) + } catch (error) { + logger.error({ error }, "Failed to send Mattermost notification") + } +} diff --git a/tsconfig.json b/tsconfig.json index 3c79456..a34062f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,6 @@ "@/*": ["./src/*"], } }, - "include":["./src/*"], + "include":["./src/*", "src/lib/config.ts"], "exclude": ["node_modules"] }