writetainer-lib 25.12.27-dev.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +375 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Erick Tran
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# Writetainer-Lib
|
|
2
|
+
|
|
3
|
+
A Portainer API accessibility library for Node.js, written in TypeScript. This library provides a convenient wrapper around the Portainer API, allowing you to easily interact with your Portainer instance to manage environments, stacks, and containers.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Authentication**: Easy authentication using Portainer API tokens
|
|
8
|
+
- **Environment Management**: Fetch and manage Portainer environments (endpoints)
|
|
9
|
+
- **Stack Management**: Create, retrieve, start, stop, update, and delete stacks
|
|
10
|
+
- **Container Management**: Full container lifecycle management (start, stop, restart, remove, etc.)
|
|
11
|
+
- **Factory Pattern**: High-level factory methods for easy stack and container creation
|
|
12
|
+
- **TypeScript Support**: Fully typed interfaces for better development experience
|
|
13
|
+
- **Logging**: Built-in logging with debug package integration
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install writetainer-lib
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
Create a `.env` file in your project root with the following variables:
|
|
24
|
+
|
|
25
|
+
```env
|
|
26
|
+
PORTAINER_URL=https://your-portainer-instance.com
|
|
27
|
+
PORTAINER_API_KEY=your-api-token-here
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
### Basic Usage
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { PortainerApi, PortainerFactory, logInfo } from 'writetainer-lib';
|
|
36
|
+
|
|
37
|
+
// Get the singleton instance of PortainerApi
|
|
38
|
+
const api = PortainerApi.getInstance();
|
|
39
|
+
|
|
40
|
+
// Check connection status
|
|
41
|
+
const isConnected = await api.getStatus();
|
|
42
|
+
logInfo('Connected:', isConnected);
|
|
43
|
+
|
|
44
|
+
// Get all stacks
|
|
45
|
+
const stacks = await api.getStacks();
|
|
46
|
+
logInfo('Stacks:', stacks);
|
|
47
|
+
|
|
48
|
+
// Get all containers
|
|
49
|
+
const containers = await api.getContainers(true);
|
|
50
|
+
logInfo('Containers:', containers);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Creating Stacks with Factory
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { PortainerFactory } from 'writetainer-lib';
|
|
57
|
+
|
|
58
|
+
const factory = PortainerFactory.getInstance();
|
|
59
|
+
|
|
60
|
+
const stackConfig = {
|
|
61
|
+
Name: "my-app-stack",
|
|
62
|
+
ComposeFile: `
|
|
63
|
+
services:
|
|
64
|
+
web:
|
|
65
|
+
image: nginx:latest
|
|
66
|
+
ports:
|
|
67
|
+
- "80:80"
|
|
68
|
+
restart: unless-stopped
|
|
69
|
+
`,
|
|
70
|
+
Env: [
|
|
71
|
+
{ name: "ENVIRONMENT", value: "production" }
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Create the stack
|
|
76
|
+
const stack = await factory.createStack(stackConfig);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Container Management
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { PortainerApi } from 'writetainer-lib';
|
|
83
|
+
|
|
84
|
+
const api = PortainerApi.getInstance();
|
|
85
|
+
|
|
86
|
+
// Start a container
|
|
87
|
+
await api.handleContainer({
|
|
88
|
+
action: 'start',
|
|
89
|
+
containerId: 'container-id-here',
|
|
90
|
+
environmentId: 1
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Stop a container
|
|
94
|
+
await api.handleContainer({
|
|
95
|
+
action: 'stop',
|
|
96
|
+
containerId: 'container-id-here'
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Remove a container with options
|
|
100
|
+
await api.handleContainer({
|
|
101
|
+
action: 'remove',
|
|
102
|
+
containerId: 'container-id-here',
|
|
103
|
+
options: {
|
|
104
|
+
force: true,
|
|
105
|
+
removeVolumes: true
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Restart a container with custom timeout
|
|
110
|
+
await api.handleContainer({
|
|
111
|
+
action: 'restart',
|
|
112
|
+
containerId: 'container-id-here',
|
|
113
|
+
options: {
|
|
114
|
+
timeout: 30000 // 30 seconds
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Stack Operations
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { PortainerApi } from 'writetainer-lib';
|
|
123
|
+
|
|
124
|
+
const api = PortainerApi.getInstance();
|
|
125
|
+
|
|
126
|
+
// Start a stack
|
|
127
|
+
await api.startStack(stackId, environmentId);
|
|
128
|
+
|
|
129
|
+
// Stop a stack
|
|
130
|
+
await api.stopStack(stackId, environmentId);
|
|
131
|
+
|
|
132
|
+
// Update a stack with new compose content
|
|
133
|
+
await api.updateStack(stackId, newComposeContent, environmentId, true);
|
|
134
|
+
|
|
135
|
+
// Redeploy a stack (stop, pull, start)
|
|
136
|
+
await api.redeployStack(stackId, environmentId);
|
|
137
|
+
|
|
138
|
+
// Delete a stack
|
|
139
|
+
await api.deleteStack(stackId, environmentId);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Environment Management
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { PortainerApi, getFirstEnvironmentId } from 'writetainer-lib';
|
|
146
|
+
|
|
147
|
+
const api = PortainerApi.getInstance();
|
|
148
|
+
|
|
149
|
+
// Get all environments
|
|
150
|
+
const environments = await api.getEnvironments();
|
|
151
|
+
|
|
152
|
+
// Get details of a specific environment
|
|
153
|
+
const envDetails = await api.getEnvironmentDetails(environmentId);
|
|
154
|
+
|
|
155
|
+
// Get first environment ID
|
|
156
|
+
const firstEnvId = await getFirstEnvironmentId();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Resource Fetching
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { PortainerApi } from 'writetainer-lib';
|
|
163
|
+
|
|
164
|
+
const api = PortainerApi.getInstance();
|
|
165
|
+
|
|
166
|
+
// Get all containers (including stopped ones)
|
|
167
|
+
const allContainers = await api.getContainers(true);
|
|
168
|
+
|
|
169
|
+
// Get running containers only
|
|
170
|
+
const runningContainers = await api.getContainers(false);
|
|
171
|
+
|
|
172
|
+
// Get container details
|
|
173
|
+
const containerDetails = await api.getContainerDetails('container-id');
|
|
174
|
+
|
|
175
|
+
// Get container stats
|
|
176
|
+
const stats = await api.getContainerStats('container-id');
|
|
177
|
+
|
|
178
|
+
// Get images
|
|
179
|
+
const images = await api.getImages(environmentId);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Utility Functions
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import {
|
|
186
|
+
getStackByName,
|
|
187
|
+
getStackById,
|
|
188
|
+
getContainerByDetails,
|
|
189
|
+
verifyStackCreation,
|
|
190
|
+
verifyContainerCreation
|
|
191
|
+
} from 'writetainer-lib';
|
|
192
|
+
|
|
193
|
+
// Find a stack by name
|
|
194
|
+
const stack = await getStackByName('my-stack-name');
|
|
195
|
+
|
|
196
|
+
// Find a stack by ID
|
|
197
|
+
const stack = await getStackById(123, environmentId);
|
|
198
|
+
|
|
199
|
+
// Find container by image or label
|
|
200
|
+
const container = await getContainerByDetails({
|
|
201
|
+
image: 'nginx:latest'
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Verify stack creation
|
|
205
|
+
const isVerified = await verifyStackCreation('my-stack', 5000, 3);
|
|
206
|
+
|
|
207
|
+
// Verify container creation
|
|
208
|
+
const isRunning = await verifyContainerCreation('my-container', 5000);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## API Reference
|
|
212
|
+
|
|
213
|
+
### Main Classes
|
|
214
|
+
|
|
215
|
+
#### `PortainerApi`
|
|
216
|
+
Singleton class that provides access to all Portainer API operations.
|
|
217
|
+
|
|
218
|
+
**Methods:**
|
|
219
|
+
- `getInstance(environmentId?: number | null)` - Get singleton instance
|
|
220
|
+
- `getEnvironments()` - Fetch all environments
|
|
221
|
+
- `getEnvironmentDetails(environmentId)` - Get environment details
|
|
222
|
+
- `getStacks()` - Get all stacks
|
|
223
|
+
- `getContainers(includeAll, environmentId?)` - Get containers
|
|
224
|
+
- `getContainerDetails(identifier, environmentId?)` - Get container details
|
|
225
|
+
- `getContainerStats(identifier, environmentId?)` - Get container stats
|
|
226
|
+
- `getImages(environmentId?)` - Get images
|
|
227
|
+
- `getStatus(environmentId?)` - Get system status
|
|
228
|
+
- `handleContainer(controls)` - Execute container actions
|
|
229
|
+
- `startStack(stackId, environmentId?)` - Start a stack
|
|
230
|
+
- `stopStack(stackId, environmentId?)` - Stop a stack
|
|
231
|
+
- `updateStack(stackId, composeContent, environmentId?, pullImage?)` - Update a stack
|
|
232
|
+
- `redeployStack(stackId, environmentId?)` - Redeploy a stack
|
|
233
|
+
- `deleteStack(stackId, environmentId?)` - Delete a stack
|
|
234
|
+
- `cleanupExistingContainer(containerName, environmentId?)` - Cleanup a container
|
|
235
|
+
- `ensureEnvId()` - Ensure environment ID is set
|
|
236
|
+
|
|
237
|
+
#### `PortainerFactory`
|
|
238
|
+
Singleton factory class for creating resources with validation.
|
|
239
|
+
|
|
240
|
+
**Methods:**
|
|
241
|
+
- `getInstance(environmentId?: number | null)` - Get singleton instance
|
|
242
|
+
- `createStack(stackData, maxRetryCount?, timeoutMs?)` - Create a new stack
|
|
243
|
+
- `createContainer(containerData, maxRetryCount?, timeoutMs?)` - Create a new container
|
|
244
|
+
|
|
245
|
+
#### `PortainerAuth`
|
|
246
|
+
Singleton class for authentication management.
|
|
247
|
+
|
|
248
|
+
**Properties:**
|
|
249
|
+
- `axiosInstance` - Configured axios instance
|
|
250
|
+
- `isValidated` - Authentication validation status
|
|
251
|
+
- `PortainerUrl` - Portainer URL
|
|
252
|
+
|
|
253
|
+
**Methods:**
|
|
254
|
+
- `getInstance()` - Get singleton instance
|
|
255
|
+
|
|
256
|
+
### Type Definitions
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
interface PortainerEnvironment {
|
|
260
|
+
Id: number;
|
|
261
|
+
Name: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
interface PortainerStack {
|
|
265
|
+
Id: number;
|
|
266
|
+
Name: string;
|
|
267
|
+
EndpointId: number;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
interface PortainerContainer {
|
|
271
|
+
Id: string;
|
|
272
|
+
Names: string[];
|
|
273
|
+
Image: string;
|
|
274
|
+
Labels: { [key: string]: string };
|
|
275
|
+
State: string;
|
|
276
|
+
Status: string;
|
|
277
|
+
// ... additional properties
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
interface PortainerImage {
|
|
281
|
+
Id: string;
|
|
282
|
+
RepoTags: string[];
|
|
283
|
+
Created: number;
|
|
284
|
+
Size: number;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
interface PortainerStackContent {
|
|
288
|
+
Name: string;
|
|
289
|
+
ComposeFile: string | any;
|
|
290
|
+
Env?: Array<{ name: string; value: string }>;
|
|
291
|
+
FromAppTemplate?: boolean;
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Logging
|
|
296
|
+
|
|
297
|
+
The library uses the `debug` package for logging. To enable logs:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# Enable all logs
|
|
301
|
+
DEBUG=portainer-api:* node your-app.js
|
|
302
|
+
|
|
303
|
+
# Enable only info logs
|
|
304
|
+
DEBUG=portainer-api:info node your-app.js
|
|
305
|
+
|
|
306
|
+
# Enable error and warning logs
|
|
307
|
+
DEBUG=portainer-api:error,portainer-api:warn node your-app.js
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
You can also use the built-in logging functions:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
import { logInfo, logWarn, logError } from 'writetainer-lib';
|
|
314
|
+
|
|
315
|
+
logInfo('This is an info message');
|
|
316
|
+
logWarn('This is a warning');
|
|
317
|
+
logError('This is an error', errorObject);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Get Stacks
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const stacks = await client.getStacks();
|
|
324
|
+
console.log(stacks);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Get Containers
|
|
328
|
+
|
|
329
|
+
Fetch all containers (running and stopped) for the default environment.
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
const containers = await client.getContainers(true);
|
|
333
|
+
console.log(containers);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### Test Connection
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const isConnected = await client.testConnection();
|
|
340
|
+
if (isConnected) {
|
|
341
|
+
console.log('Connected to Portainer!');
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## API Reference
|
|
346
|
+
|
|
347
|
+
### `PortainerApiClient`
|
|
348
|
+
|
|
349
|
+
#### Constructor
|
|
350
|
+
`new PortainerApiClient(portainerUrl: string, apiToken: string, environmentId?: number | null)`
|
|
351
|
+
|
|
352
|
+
#### Methods
|
|
353
|
+
|
|
354
|
+
- `getEnvironments(): Promise<PortainerEnvironment[]>`
|
|
355
|
+
- Fetches a list of all Portainer environments.
|
|
356
|
+
|
|
357
|
+
- `getEnvironment(environmentId: number): Promise<PortainerEnvironment>`
|
|
358
|
+
- Fetches details of a specific environment.
|
|
359
|
+
|
|
360
|
+
- `getStacks(): Promise<PortainerStack[]>`
|
|
361
|
+
- Fetches a list of all stacks.
|
|
362
|
+
|
|
363
|
+
- `getContainers(includeAll: boolean): Promise<PortainerContainer[] | undefined>`
|
|
364
|
+
- Fetches a list of containers for the current environment.
|
|
365
|
+
- `includeAll`: Set to `true` to include stopped containers.
|
|
366
|
+
|
|
367
|
+
- `testConnection(): Promise<boolean>`
|
|
368
|
+
- Tests the connection to the Portainer API.
|
|
369
|
+
|
|
370
|
+
- `DefaultEnvironmentId` (Getter/Setter)
|
|
371
|
+
- Get or set the default environment ID used for container operations.
|
|
372
|
+
|
|
373
|
+
## License
|
|
374
|
+
|
|
375
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "writetainer-lib",
|
|
3
|
+
"version": "25.12.27-dev.9",
|
|
4
|
+
"description": "A TypeScript library for interacting with the Portainer API to manage Docker containers and stacks programmatically.",
|
|
5
|
+
"homepage": "https://github.com/enVId-tech/Writetainer-Lib#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/enVId-tech/Writetainer-Lib/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/enVId-tech/Writetainer-Lib.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "envid-tech",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "vitest",
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"ncu": "npx npm-check-updates -u && npm install"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"axios": "^1.13.6",
|
|
22
|
+
"debug": "^4.4.3",
|
|
23
|
+
"dotenv": "^17.3.1",
|
|
24
|
+
"typescript": "^5.9.3"
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
41
|
+
"@types/debug": "^4.1.13",
|
|
42
|
+
"@types/node": "^25.5.0",
|
|
43
|
+
"vitest": "^4.1.0"
|
|
44
|
+
},
|
|
45
|
+
"type": "module"
|
|
46
|
+
}
|