diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..e5c63b4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,13 @@ +name: Build example container + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build Docker image + run: docker build -t kuberhealthy-js-check . diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ebde67c --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,22 @@ +name: Publish package + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + registry-url: https://npm.pkg.github.com + - run: npm publish + working-directory: client + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index fb6fbe0..de2023d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM node:20-alpine WORKDIR /app COPY package.json ./ +COPY client ./client RUN npm install --production COPY check.js ./ CMD ["node", "check.js"] diff --git a/README.md b/README.md index da459a4..c6bc923 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,34 @@ # JavaScript Kuberhealthy Client -This directory contains an example external check for [Kuberhealthy](https://github.com/kuberhealthy/kuberhealthy) written in JavaScript. The script demonstrates how to report a successful run or a failure back to Kuberhealthy using environment variables provided to every checker pod. +This repository contains a small client library and example external check for [Kuberhealthy](https://github.com/kuberhealthy/kuberhealthy). -## Usage +The reusable client lives in the `client/` directory and is published as `@kuberhealthy/client`. It can be imported into your own Node.js applications to report check results back to Kuberhealthy. An example checker using the client is provided in `check.js`. -1. **Add your logic**: edit `check.js` and replace the placeholder section in `main` with your own check logic. Call `report(true, [])` when the check succeeds or `report(false, ["message"])` on failure. +## Client Library + +The package is published to the GitHub Packages npm registry under `@kuberhealthy/client`. + +Install it by configuring npm to use the GitHub Packages registry for the `@kuberhealthy` scope: + +```bash +echo "@kuberhealthy:registry=https://npm.pkg.github.com" >> ~/.npmrc +npm install @kuberhealthy/client +``` + +Use the client in your code: + +```javascript +const { KuberhealthyClient } = require('@kuberhealthy/client'); + +const client = new KuberhealthyClient(process.env.KH_REPORTING_URL, process.env.KH_RUN_UUID); +await client.report(true, []); +``` + +Node.js 18 or newer is required for the built in `fetch` API used by the client. + +## Example Checker + +1. **Add your logic**: edit `check.js` and replace the placeholder section in `main` with your own check logic. Call `client.report(true, [])` when the check succeeds or `client.report(false, ["message"])` on failure. 2. **Build the image**: run `make build IMAGE=my-registry/my-check:tag` to build a container image containing your check. 3. **Push the image**: `make push IMAGE=my-registry/my-check:tag`. 4. **Create a KuberhealthyCheck**: write a khcheck resource that references your image and apply it to clusters where Kuberhealthy runs. @@ -14,7 +38,7 @@ The check relies on two environment variables set automatically by Kuberhealthy: - `KH_REPORTING_URL` – the endpoint where status reports are posted. - `KH_RUN_UUID` – the UUID for this check run. It must be sent back in the `kh-run-uuid` header. -## Example khcheck +### Example khcheck ```yaml apiVersion: kuberhealthy.github.io/v2 diff --git a/check.js b/check.js index be672c6..fec0cac 100644 --- a/check.js +++ b/check.js @@ -1,3 +1,5 @@ +const { KuberhealthyClient } = require('@kuberhealthy/client'); + const reportingURL = process.env.KH_REPORTING_URL; const runUUID = process.env.KH_RUN_UUID; @@ -6,34 +8,17 @@ if (!reportingURL || !runUUID) { process.exit(1); } -// report sends a result to Kuberhealthy -async function report(ok, errors) { - const res = await fetch(reportingURL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'kh-run-uuid': runUUID, - }, - body: JSON.stringify({ ok, errors }), - }); - - if (res.ok) { - return; - } - - const text = await res.text(); - throw new Error(`Kuberhealthy responded with ${res.status}: ${text}`); -} +const client = new KuberhealthyClient(reportingURL, runUUID); async function main() { try { // Add your check logic here. - await report(true, []); + await client.report(true, []); console.log('Reported success to Kuberhealthy'); } catch (err) { console.error('Check logic failed:', err); try { - await report(false, [err.message]); + await client.report(false, [err.message]); } catch (e) { console.error('Failed to report failure:', e); } @@ -42,5 +27,3 @@ async function main() { } main(); - -module.exports = { report }; diff --git a/client/index.js b/client/index.js new file mode 100644 index 0000000..74903e0 --- /dev/null +++ b/client/index.js @@ -0,0 +1,27 @@ +class KuberhealthyClient { + constructor(reportingURL, runUUID) { + if (!reportingURL || !runUUID) { + throw new Error('reportingURL and runUUID are required'); + } + this.reportingURL = reportingURL; + this.runUUID = runUUID; + } + + async report(ok, errors) { + const res = await fetch(this.reportingURL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'kh-run-uuid': this.runUUID, + }, + body: JSON.stringify({ ok, errors }), + }); + + if (!res.ok) { + const text = await res.text(); + throw new Error(`Kuberhealthy responded with ${res.status}: ${text}`); + } + } +} + +module.exports = { KuberhealthyClient }; diff --git a/client/package.json b/client/package.json new file mode 100644 index 0000000..47df22d --- /dev/null +++ b/client/package.json @@ -0,0 +1,13 @@ +{ + "name": "@kuberhealthy/client", + "version": "0.1.0", + "description": "Node.js client for Kuberhealthy", + "main": "index.js", + "files": ["index.js"], + "publishConfig": { + "registry": "https://npm.pkg.github.com" + }, + "engines": { + "node": ">=18" + } +} diff --git a/package.json b/package.json index 737beaa..4e28427 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,16 @@ { - "name": "kuberhealthy-javascript-client", + "name": "kuberhealthy-check-example", "version": "0.1.0", - "description": "Example Kuberhealthy external check written in JavaScript", + "private": true, + "description": "Example external check for Kuberhealthy using the JavaScript client", "main": "check.js", "scripts": { "start": "node check.js" }, - "dependencies": {} + "engines": { + "node": ">=18" + }, + "dependencies": { + "@kuberhealthy/client": "file:./client" + } }