-
-
Notifications
You must be signed in to change notification settings - Fork 269
Add InfluxDB module #1445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add InfluxDB module #1445
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # InfluxDB | ||
|
|
||
| ## Install | ||
|
|
||
| ```bash | ||
| npm install @testcontainers/influxdb --save-dev | ||
| ``` | ||
|
|
||
| ## Examples | ||
|
|
||
| The InfluxDB 2.x examples use the following libraries: | ||
|
|
||
| - [@influxdata/influxdb-client](https://www.npmjs.com/package/@influxdata/influxdb-client) | ||
|
|
||
| npm install @influxdata/influxdb-client | ||
|
|
||
| `InfluxDBContainer` supports both InfluxDB 2.x and the legacy 1.x line. The major version is derived from the image tag, so substitute `IMAGE` with a `2.x` tag (the default flavour) or a `1.x` tag from the [container registry](https://hub.docker.com/_/influxdb). | ||
|
|
||
| ### Write and query points (InfluxDB 2.x) | ||
|
|
||
| <!--codeinclude--> | ||
| [](../../packages/modules/influxdb/src/influxdb-container.test.ts) inside_block:influxdb2WriteAndQuery | ||
| <!--/codeinclude--> | ||
|
|
||
| ### Write and query points (InfluxDB 1.x) | ||
|
|
||
| <!--codeinclude--> | ||
| [](../../packages/modules/influxdb/src/influxdb-container.test.ts) inside_block:influxdb1WriteAndQuery | ||
| <!--/codeinclude--> | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| FROM influxdb:2.7 | ||
| FROM influxdb:1.11 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| { | ||
| "name": "@testcontainers/influxdb", | ||
| "version": "12.1.0", | ||
| "license": "MIT", | ||
| "keywords": [ | ||
| "influxdb", | ||
| "influx", | ||
| "timeseries", | ||
| "testing", | ||
| "docker", | ||
| "testcontainers" | ||
| ], | ||
| "description": "InfluxDB module for Testcontainers", | ||
| "homepage": "https://github.com/testcontainers/testcontainers-node#readme", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/testcontainers/testcontainers-node.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/testcontainers/testcontainers-node/issues" | ||
| }, | ||
| "main": "build/index.js", | ||
| "files": [ | ||
| "build" | ||
| ], | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "scripts": { | ||
| "prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .", | ||
| "build": "tsc --project tsconfig.build.json" | ||
| }, | ||
| "devDependencies": { | ||
| "@influxdata/influxdb-client": "^1.35.0" | ||
| }, | ||
| "dependencies": { | ||
| "testcontainers": "^12.1.0" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { InfluxDBContainer, StartedInfluxDBContainer } from "./influxdb-container"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| import { InfluxDB, Point } from "@influxdata/influxdb-client"; | ||
| import { expect } from "vitest"; | ||
| import { getImage } from "../../../testcontainers/src/utils/test-helper"; | ||
| import { InfluxDBContainer } from "./influxdb-container"; | ||
|
|
||
| const INFLUXDB2_IMAGE = getImage(__dirname, 0); | ||
| const INFLUXDB1_IMAGE = getImage(__dirname, 1); | ||
|
|
||
| describe("InfluxDBContainer", { timeout: 240_000 }, () => { | ||
| describe("InfluxDB 2.x", () => { | ||
| it("should start and expose the connection details", async () => { | ||
| await using container = await new InfluxDBContainer(INFLUXDB2_IMAGE).start(); | ||
|
|
||
| expect(container.isInfluxDB2()).toBe(true); | ||
| expect(container.getPort()).toBeGreaterThan(0); | ||
| expect(container.getUrl()).toEqual(`http://${container.getHost()}:${container.getPort()}`); | ||
| expect(container.getOrganization()).toBe("test-org"); | ||
| expect(container.getBucket()).toBe("test-bucket"); | ||
|
|
||
| const ping = await fetch(`${container.getUrl()}/ping`); | ||
| expect(ping.status).toBe(204); | ||
| }); | ||
|
|
||
| it("should write and query points with the official client", async () => { | ||
| // influxdb2WriteAndQuery { | ||
| await using container = await new InfluxDBContainer(INFLUXDB2_IMAGE).withAdminToken("my-secret-token").start(); | ||
|
Comment on lines
+25
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Make the extracted documentation examples self-contained. The Include the required imports and a concrete image declaration in each documented block, or replace the Also applies to: 64-65 🤖 Prompt for AI Agents |
||
|
|
||
| const influxDB = new InfluxDB({ url: container.getUrl(), token: container.getAdminToken() }); | ||
|
|
||
| const writeApi = influxDB.getWriteApi(container.getOrganization(), container.getBucket()); | ||
| writeApi.writePoint(new Point("temperature").tag("location", "room1").floatField("value", 23.5)); | ||
| await writeApi.close(); | ||
|
|
||
| const queryApi = influxDB.getQueryApi(container.getOrganization()); | ||
| const rows = await queryApi.collectRows<{ _value: number }>( | ||
| `from(bucket: "${container.getBucket()}") |> range(start: -1h) |> filter(fn: (r) => r._measurement == "temperature")` | ||
| ); | ||
|
|
||
| expect(rows.length).toBeGreaterThan(0); | ||
| expect(rows[0]._value).toBe(23.5); | ||
| // } | ||
| }); | ||
|
|
||
| it("should apply custom configuration", async () => { | ||
| await using container = await new InfluxDBContainer(INFLUXDB2_IMAGE) | ||
| .withUsername("custom-user") | ||
| .withPassword("custom-password") | ||
| .withOrganization("custom-org") | ||
| .withBucket("custom-bucket") | ||
| .withRetention("24h") | ||
| .withAdminToken("custom-token") | ||
| .start(); | ||
|
|
||
| expect(container.getUsername()).toBe("custom-user"); | ||
| expect(container.getPassword()).toBe("custom-password"); | ||
| expect(container.getOrganization()).toBe("custom-org"); | ||
| expect(container.getBucket()).toBe("custom-bucket"); | ||
| expect(container.getAdminToken()).toBe("custom-token"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("InfluxDB 1.x", () => { | ||
| it("should start a 1.x database and write/query over HTTP", async () => { | ||
| // influxdb1WriteAndQuery { | ||
| await using container = await new InfluxDBContainer(INFLUXDB1_IMAGE) | ||
| .withDatabase("testdb") | ||
| .withAuthEnabled(false) | ||
| .start(); | ||
|
|
||
| expect(container.isInfluxDB2()).toBe(false); | ||
| expect(container.getDatabase()).toBe("testdb"); | ||
|
|
||
| const writeResponse = await fetch(`${container.getUrl()}/write?db=${container.getDatabase()}`, { | ||
| method: "POST", | ||
| body: "cpu_load,host=server01 value=0.64", | ||
| }); | ||
| expect(writeResponse.status).toBe(204); | ||
|
|
||
| const query = encodeURIComponent("SELECT * FROM cpu_load"); | ||
| const queryResponse = await fetch(`${container.getUrl()}/query?db=${container.getDatabase()}&q=${query}`); | ||
| expect(queryResponse.status).toBe(200); | ||
|
|
||
| const body = (await queryResponse.json()) as { results: unknown[] }; | ||
| expect(body.results).toBeDefined(); | ||
| // } | ||
| }); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use a fenced code block for the client installation command.
Line 15 uses an indented code block. This triggers markdownlint MD046.
Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 15-15: Code block style
Expected: fenced; Actual: indented
(MD046, code-block-style)
🤖 Prompt for AI Agents
Source: Linters/SAST tools