@nexusgpu/repterm-plugin-kubectl 0.1.0
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/README.md +277 -0
- package/dist/index.d.ts +314 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +544 -0
- package/dist/matchers.d.ts +113 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +527 -0
- package/dist/plugin-kubectl/examples/00-simple-demo.d.ts +10 -0
- package/dist/plugin-kubectl/examples/00-simple-demo.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/00-simple-demo.js +51 -0
- package/dist/plugin-kubectl/examples/01-basic-kubectl.d.ts +13 -0
- package/dist/plugin-kubectl/examples/01-basic-kubectl.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/01-basic-kubectl.js +86 -0
- package/dist/plugin-kubectl/examples/02-debugging.d.ts +13 -0
- package/dist/plugin-kubectl/examples/02-debugging.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/02-debugging.js +80 -0
- package/dist/plugin-kubectl/examples/03-resource-management.d.ts +13 -0
- package/dist/plugin-kubectl/examples/03-resource-management.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/03-resource-management.js +134 -0
- package/dist/plugin-kubectl/examples/04-rollout.d.ts +13 -0
- package/dist/plugin-kubectl/examples/04-rollout.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/04-rollout.js +122 -0
- package/dist/plugin-kubectl/examples/05-matchers.d.ts +15 -0
- package/dist/plugin-kubectl/examples/05-matchers.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/05-matchers.js +138 -0
- package/dist/plugin-kubectl/examples/06-advanced.d.ts +14 -0
- package/dist/plugin-kubectl/examples/06-advanced.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/06-advanced.js +140 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.d.ts +14 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.js +66 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.d.ts +14 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.js +145 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.d.ts +13 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.js +123 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.d.ts +17 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.js +96 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/04-release.d.ts +13 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/04-release.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/04-release.js +117 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.d.ts +14 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.js +145 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.d.ts +14 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.js +235 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.d.ts +15 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.js +146 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.d.ts +13 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.js +141 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.d.ts +15 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.js +256 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/_config.d.ts +71 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/_config.d.ts.map +1 -0
- package/dist/plugin-kubectl/examples/tensor-fusion/_config.js +159 -0
- package/dist/plugin-kubectl/src/index.d.ts +314 -0
- package/dist/plugin-kubectl/src/index.d.ts.map +1 -0
- package/dist/plugin-kubectl/src/index.js +545 -0
- package/dist/plugin-kubectl/src/matchers.d.ts +113 -0
- package/dist/plugin-kubectl/src/matchers.d.ts.map +1 -0
- package/dist/plugin-kubectl/src/matchers.js +527 -0
- package/dist/plugin-kubectl/src/result.d.ts +80 -0
- package/dist/plugin-kubectl/src/result.d.ts.map +1 -0
- package/dist/plugin-kubectl/src/result.js +134 -0
- package/dist/repterm/src/api/describe.d.ts +18 -0
- package/dist/repterm/src/api/describe.d.ts.map +1 -0
- package/dist/repterm/src/api/describe.js +32 -0
- package/dist/repterm/src/api/expect.d.ts +43 -0
- package/dist/repterm/src/api/expect.d.ts.map +1 -0
- package/dist/repterm/src/api/expect.js +166 -0
- package/dist/repterm/src/api/hooks.d.ts +178 -0
- package/dist/repterm/src/api/hooks.d.ts.map +1 -0
- package/dist/repterm/src/api/hooks.js +230 -0
- package/dist/repterm/src/api/steps.d.ts +45 -0
- package/dist/repterm/src/api/steps.d.ts.map +1 -0
- package/dist/repterm/src/api/steps.js +105 -0
- package/dist/repterm/src/api/test.d.ts +101 -0
- package/dist/repterm/src/api/test.d.ts.map +1 -0
- package/dist/repterm/src/api/test.js +206 -0
- package/dist/repterm/src/index.d.ts +15 -0
- package/dist/repterm/src/index.d.ts.map +1 -0
- package/dist/repterm/src/index.js +23 -0
- package/dist/repterm/src/plugin/index.d.ts +47 -0
- package/dist/repterm/src/plugin/index.d.ts.map +1 -0
- package/dist/repterm/src/plugin/index.js +85 -0
- package/dist/repterm/src/plugin/withPlugins.d.ts +71 -0
- package/dist/repterm/src/plugin/withPlugins.d.ts.map +1 -0
- package/dist/repterm/src/plugin/withPlugins.js +100 -0
- package/dist/repterm/src/runner/models.d.ts +261 -0
- package/dist/repterm/src/runner/models.d.ts.map +1 -0
- package/dist/repterm/src/runner/models.js +4 -0
- package/dist/result.d.ts +80 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +134 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# @nexusgpu/repterm-plugin-kubectl
|
|
2
|
+
|
|
3
|
+
Kubernetes testing plugin for Repterm. Provides kubectl operations and expect matchers for K8s resources.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @nexusgpu/repterm-plugin-kubectl
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { defineConfig, createTestWithPlugins, expect } from 'repterm';
|
|
15
|
+
import { kubectlPlugin, pod, deployment } from '@nexusgpu/repterm-plugin-kubectl';
|
|
16
|
+
|
|
17
|
+
const config = defineConfig({
|
|
18
|
+
plugins: [kubectlPlugin({ namespace: 'default' })] as const,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const test = createTestWithPlugins(config);
|
|
22
|
+
|
|
23
|
+
test('deploy nginx', async (ctx) => {
|
|
24
|
+
const { kubectl } = ctx.plugins;
|
|
25
|
+
|
|
26
|
+
await kubectl.apply(`
|
|
27
|
+
apiVersion: v1
|
|
28
|
+
kind: Pod
|
|
29
|
+
metadata:
|
|
30
|
+
name: nginx
|
|
31
|
+
spec:
|
|
32
|
+
containers:
|
|
33
|
+
- name: nginx
|
|
34
|
+
image: nginx:alpine
|
|
35
|
+
`);
|
|
36
|
+
|
|
37
|
+
await kubectl.waitForPod('nginx', 'Running');
|
|
38
|
+
await expect(pod(kubectl, 'nginx')).toBeRunning();
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API Reference
|
|
43
|
+
|
|
44
|
+
### Plugin Options
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
kubectlPlugin({
|
|
48
|
+
namespace?: string; // Default namespace (default: 'default')
|
|
49
|
+
kubeconfig?: string; // Path to kubeconfig file
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Core Methods
|
|
54
|
+
|
|
55
|
+
| Method | Description |
|
|
56
|
+
|--------|-------------|
|
|
57
|
+
| `run(args)` | Execute raw kubectl command |
|
|
58
|
+
| `command(args)` | Get kubectl command string with namespace |
|
|
59
|
+
| `apply(yaml)` | Create/update resource from YAML |
|
|
60
|
+
| `delete(resource, name, options?)` | Delete resource |
|
|
61
|
+
| `get<T>(resource, name?, options?)` | Get resource as JSON |
|
|
62
|
+
| `getJsonPath<T>(resource, name, jsonPath, options?)` | Get specific field via JSONPath |
|
|
63
|
+
| `exists(resource, name)` | Check if resource exists |
|
|
64
|
+
| `clusterInfo()` | Get cluster connection info |
|
|
65
|
+
| `setNamespace(ns)` | Set current namespace |
|
|
66
|
+
| `getNamespace()` | Get current namespace |
|
|
67
|
+
|
|
68
|
+
### Get Options
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
interface GetOptions {
|
|
72
|
+
selector?: string; // Label selector (-l)
|
|
73
|
+
fieldSelector?: string; // Field selector
|
|
74
|
+
allNamespaces?: boolean; // All namespaces (-A)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Examples
|
|
78
|
+
await kubectl.get('pod', undefined, { selector: 'app=nginx' });
|
|
79
|
+
await kubectl.get('pod', undefined, { allNamespaces: true });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### JSONPath Query
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Get specific field value
|
|
86
|
+
const phase = await kubectl.getJsonPath<string>('pod', 'nginx', '{.status.phase}');
|
|
87
|
+
const tflops = await kubectl.getJsonPath<number>('gpu', 'gpu-0', '{.status.available.tflops}');
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Cluster Info
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const info = await kubectl.clusterInfo();
|
|
94
|
+
// {
|
|
95
|
+
// reachable: true,
|
|
96
|
+
// controlPlane: 'https://...',
|
|
97
|
+
// serverVersion: 'v1.28.0',
|
|
98
|
+
// coreDNS: 'https://...'
|
|
99
|
+
// }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Wait Methods
|
|
103
|
+
|
|
104
|
+
| Method | Description |
|
|
105
|
+
|--------|-------------|
|
|
106
|
+
| `waitForPod(name, status?, timeout?)` | Wait for pod status |
|
|
107
|
+
| `wait(resource, name, condition, options?)` | Wait for condition |
|
|
108
|
+
| `waitForJsonPath(resource, name, jsonPath, value, timeout?)` | Wait for field value |
|
|
109
|
+
| `waitForReplicas(resource, name, count, timeout?)` | Wait for replica count |
|
|
110
|
+
| `waitForService(name, timeout?)` | Wait for service endpoints |
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Wait for pod running
|
|
114
|
+
await kubectl.waitForPod('nginx', 'Running', 60000);
|
|
115
|
+
|
|
116
|
+
// Wait for custom condition
|
|
117
|
+
await kubectl.wait('deployment', 'nginx', 'Available');
|
|
118
|
+
|
|
119
|
+
// Wait for JSONPath field value
|
|
120
|
+
await kubectl.waitForJsonPath('tensorfusionworkload', 'my-workload', '{.status.phase}', 'Running');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Resource Management
|
|
124
|
+
|
|
125
|
+
| Method | Description |
|
|
126
|
+
|--------|-------------|
|
|
127
|
+
| `logs(pod, options?)` | Get pod logs |
|
|
128
|
+
| `exec(pod, command, options?)` | Execute command in pod |
|
|
129
|
+
| `describe(resource, name?)` | Get resource description |
|
|
130
|
+
| `scale(resource, name, replicas)` | Scale resource |
|
|
131
|
+
| `patch(resource, name, patch, type?)` | Patch resource |
|
|
132
|
+
| `label(resource, name, labels)` | Update labels |
|
|
133
|
+
| `annotate(resource, name, annotations)` | Update annotations |
|
|
134
|
+
|
|
135
|
+
### Rollout Management
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Get rollout status
|
|
139
|
+
const status = await kubectl.rollout.status('deployment', 'nginx');
|
|
140
|
+
|
|
141
|
+
// Rollout operations
|
|
142
|
+
await kubectl.rollout.restart('deployment', 'nginx');
|
|
143
|
+
await kubectl.rollout.pause('deployment', 'nginx');
|
|
144
|
+
await kubectl.rollout.resume('deployment', 'nginx');
|
|
145
|
+
await kubectl.rollout.undo('deployment', 'nginx', revision?);
|
|
146
|
+
const history = await kubectl.rollout.history('deployment', 'nginx');
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Advanced Features
|
|
150
|
+
|
|
151
|
+
| Method | Description |
|
|
152
|
+
|--------|-------------|
|
|
153
|
+
| `portForward(resource, ports, options?)` | Port forward |
|
|
154
|
+
| `getEvents(options?)` | Get cluster events |
|
|
155
|
+
| `getNodes(options?)` | Get node info |
|
|
156
|
+
| `cp(source, dest, options?)` | Copy files to/from pod |
|
|
157
|
+
|
|
158
|
+
## Resource Wrappers
|
|
159
|
+
|
|
160
|
+
Create typed resource references for matchers:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import {
|
|
164
|
+
pod, deployment, service, statefulset, job, configmap, secret,
|
|
165
|
+
// Tensor Fusion CRDs
|
|
166
|
+
gpupool, gpu, tensorfusionworkload, tensorfusionconnection,
|
|
167
|
+
// Generic
|
|
168
|
+
resource, crd
|
|
169
|
+
} from '@nexusgpu/repterm-plugin-kubectl';
|
|
170
|
+
|
|
171
|
+
// Standard resources
|
|
172
|
+
const p = pod(kubectl, 'nginx');
|
|
173
|
+
const d = deployment(kubectl, 'nginx');
|
|
174
|
+
|
|
175
|
+
// Tensor Fusion CRDs
|
|
176
|
+
const pool = gpupool(kubectl, 'shared-pool');
|
|
177
|
+
const workload = tensorfusionworkload(kubectl, 'my-workload');
|
|
178
|
+
|
|
179
|
+
// Generic resource
|
|
180
|
+
const custom = resource(kubectl, 'myresource', 'name');
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Expect Matchers
|
|
184
|
+
|
|
185
|
+
### Existence
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
await expect(pod(kubectl, 'nginx')).toExistInCluster();
|
|
189
|
+
await expect(pod(kubectl, 'old-pod')).toNotExistInCluster();
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Pod Status
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
await expect(pod(kubectl, 'nginx')).toBeRunning(timeout?);
|
|
196
|
+
await expect(pod(kubectl, 'nginx')).toHavePhase('Running');
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Replicas
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
await expect(deployment(kubectl, 'nginx')).toHaveReplicas(3);
|
|
203
|
+
await expect(deployment(kubectl, 'nginx')).toHaveReadyReplicas(3);
|
|
204
|
+
await expect(deployment(kubectl, 'nginx')).toHaveAvailableReplicas(3);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Conditions
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
await expect(deployment(kubectl, 'nginx')).toBeAvailable();
|
|
211
|
+
await expect(deployment(kubectl, 'nginx')).toHaveCondition('Available', 'True');
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Labels & Annotations
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
await expect(pod(kubectl, 'nginx')).toHaveLabel('app', 'nginx');
|
|
218
|
+
await expect(pod(kubectl, 'nginx')).toHaveLabel('app'); // key exists
|
|
219
|
+
await expect(pod(kubectl, 'nginx')).toHaveAnnotation('description', 'My app');
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Status Fields (Generic)
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// Check any status field (supports nested paths)
|
|
226
|
+
await expect(gpupool(kubectl, 'shared')).toHaveStatusField('phase', 'Running');
|
|
227
|
+
await expect(gpu(kubectl, 'gpu-0')).toHaveStatusField('available.tflops', '312');
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Examples
|
|
231
|
+
|
|
232
|
+
See `examples/` directory:
|
|
233
|
+
|
|
234
|
+
| File | Description |
|
|
235
|
+
|------|-------------|
|
|
236
|
+
| `00-simple-demo.ts` | Basic plugin setup |
|
|
237
|
+
| `01-basic-kubectl.ts` | Core CRUD operations |
|
|
238
|
+
| `02-debugging.ts` | logs, exec, describe |
|
|
239
|
+
| `03-resource-management.ts` | scale, patch, label |
|
|
240
|
+
| `04-rollout.ts` | Rollout management |
|
|
241
|
+
| `05-matchers.ts` | All matchers demo |
|
|
242
|
+
| `06-advanced.ts` | Port forward, events, nodes |
|
|
243
|
+
| `tensor-fusion/` | Tensor Fusion GPU allocation tests |
|
|
244
|
+
|
|
245
|
+
Run examples:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Basic demo (no cluster needed)
|
|
249
|
+
bun run repterm packages/plugin-kubectl/examples/00-simple-demo.ts
|
|
250
|
+
|
|
251
|
+
# With K8s cluster
|
|
252
|
+
bun run repterm packages/plugin-kubectl/examples/01-basic-kubectl.ts
|
|
253
|
+
|
|
254
|
+
# Tensor Fusion tests
|
|
255
|
+
bun run repterm packages/plugin-kubectl/examples/tensor-fusion/
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Recording Mode
|
|
259
|
+
|
|
260
|
+
Tests marked with `{ record: true }` can be recorded:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
describe('My tests', { record: true }, () => {
|
|
264
|
+
test('creates pod', async (ctx) => {
|
|
265
|
+
// ...
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Run with recording
|
|
272
|
+
bun run repterm --record packages/plugin-kubectl/examples/
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## License
|
|
276
|
+
|
|
277
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kubectl Plugin for Repterm
|
|
3
|
+
*
|
|
4
|
+
* Provides Kubernetes-specific testing utilities and commands.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { type BasePluginContext } from 'repterm-api';
|
|
9
|
+
import { ApplyResult, DeleteResult, PatchResult, ScaleResult, LabelResult, WaitResult } from './result.js';
|
|
10
|
+
/**
|
|
11
|
+
* Kubectl context extension
|
|
12
|
+
* This will be available to downstream plugins
|
|
13
|
+
*/
|
|
14
|
+
export interface KubectlContext {
|
|
15
|
+
kubectl: {
|
|
16
|
+
namespace: string;
|
|
17
|
+
kubeconfig?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for kubectl logs command
|
|
22
|
+
*/
|
|
23
|
+
export interface LogsOptions {
|
|
24
|
+
/** Specify container name */
|
|
25
|
+
container?: string;
|
|
26
|
+
/** Follow log output (-f) */
|
|
27
|
+
follow?: boolean;
|
|
28
|
+
/** Number of lines to show from the end */
|
|
29
|
+
tail?: number;
|
|
30
|
+
/** Time range (e.g., '5m', '1h') */
|
|
31
|
+
since?: string;
|
|
32
|
+
/** Show logs from previous container instance */
|
|
33
|
+
previous?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Options for kubectl exec command
|
|
37
|
+
*/
|
|
38
|
+
export interface ExecOptions {
|
|
39
|
+
/** Specify container name */
|
|
40
|
+
container?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Options for kubectl wait command
|
|
44
|
+
*/
|
|
45
|
+
export interface WaitOptions {
|
|
46
|
+
/** Timeout in milliseconds */
|
|
47
|
+
timeout?: number;
|
|
48
|
+
/** Wait for resource deletion */
|
|
49
|
+
forDelete?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Rollout status information
|
|
53
|
+
*/
|
|
54
|
+
export interface RolloutStatus {
|
|
55
|
+
/** Whether the rollout is complete */
|
|
56
|
+
ready: boolean;
|
|
57
|
+
/** Total number of replicas */
|
|
58
|
+
replicas: number;
|
|
59
|
+
/** Number of updated replicas */
|
|
60
|
+
updatedReplicas: number;
|
|
61
|
+
/** Number of available replicas */
|
|
62
|
+
availableReplicas: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Rollout history entry
|
|
66
|
+
*/
|
|
67
|
+
export interface RolloutHistoryEntry {
|
|
68
|
+
/** Revision number */
|
|
69
|
+
revision: number;
|
|
70
|
+
/** Change cause annotation */
|
|
71
|
+
changeCause?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Rollout management methods
|
|
75
|
+
*/
|
|
76
|
+
export interface RolloutMethods {
|
|
77
|
+
/** Get rollout status */
|
|
78
|
+
status: (resource: string, name: string) => Promise<RolloutStatus>;
|
|
79
|
+
/** Get rollout history */
|
|
80
|
+
history: (resource: string, name: string) => Promise<RolloutHistoryEntry[]>;
|
|
81
|
+
/** Undo rollout to previous or specific revision */
|
|
82
|
+
undo: (resource: string, name: string, revision?: number) => Promise<void>;
|
|
83
|
+
/** Restart rollout (trigger new deployment) */
|
|
84
|
+
restart: (resource: string, name: string) => Promise<void>;
|
|
85
|
+
/** Pause rollout */
|
|
86
|
+
pause: (resource: string, name: string) => Promise<void>;
|
|
87
|
+
/** Resume paused rollout */
|
|
88
|
+
resume: (resource: string, name: string) => Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Port forward options
|
|
92
|
+
*/
|
|
93
|
+
export interface PortForwardOptions {
|
|
94
|
+
/** Listen address (default: 127.0.0.1) */
|
|
95
|
+
address?: string;
|
|
96
|
+
/** Delay in ms to wait for port-forward to establish (default: 2000) */
|
|
97
|
+
delay?: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Port forward handle for managing port-forward lifecycle
|
|
101
|
+
*/
|
|
102
|
+
export interface PortForwardHandle {
|
|
103
|
+
/** Local port being forwarded */
|
|
104
|
+
localPort: number;
|
|
105
|
+
/** Stop the port-forward */
|
|
106
|
+
stop: () => Promise<void>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Service endpoint information
|
|
110
|
+
*/
|
|
111
|
+
export interface ServiceEndpoint {
|
|
112
|
+
/** Cluster IP of the service */
|
|
113
|
+
clusterIP: string;
|
|
114
|
+
/** Service port */
|
|
115
|
+
port: number;
|
|
116
|
+
/** List of endpoint IPs */
|
|
117
|
+
endpoints: string[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Event options
|
|
121
|
+
*/
|
|
122
|
+
export interface EventOptions {
|
|
123
|
+
/** Field selector for filtering events */
|
|
124
|
+
fieldSelector?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Kubernetes event
|
|
128
|
+
*/
|
|
129
|
+
export interface K8sEvent {
|
|
130
|
+
/** Event type (Normal or Warning) */
|
|
131
|
+
type: 'Normal' | 'Warning';
|
|
132
|
+
/** Reason for the event */
|
|
133
|
+
reason: string;
|
|
134
|
+
/** Event message */
|
|
135
|
+
message: string;
|
|
136
|
+
/** Object involved in the event */
|
|
137
|
+
involvedObject: {
|
|
138
|
+
kind: string;
|
|
139
|
+
name: string;
|
|
140
|
+
};
|
|
141
|
+
/** Last timestamp of the event */
|
|
142
|
+
lastTimestamp: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Node information
|
|
146
|
+
*/
|
|
147
|
+
export interface NodeInfo {
|
|
148
|
+
/** Node name */
|
|
149
|
+
name: string;
|
|
150
|
+
/** Node status */
|
|
151
|
+
status: 'Ready' | 'NotReady';
|
|
152
|
+
/** Node roles */
|
|
153
|
+
roles: string[];
|
|
154
|
+
/** Kubernetes version */
|
|
155
|
+
version: string;
|
|
156
|
+
/** Internal IP address */
|
|
157
|
+
internalIP: string;
|
|
158
|
+
}
|
|
159
|
+
export interface CpOptions {
|
|
160
|
+
/** Container name */
|
|
161
|
+
container?: string;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Delete options
|
|
165
|
+
*/
|
|
166
|
+
export interface DeleteOptions {
|
|
167
|
+
/** Force delete with --grace-period=0 --force */
|
|
168
|
+
force?: boolean;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Options for kubectl get command
|
|
172
|
+
*/
|
|
173
|
+
export interface GetOptions {
|
|
174
|
+
/** Label selector (-l) */
|
|
175
|
+
selector?: string;
|
|
176
|
+
/** Field selector (--field-selector) */
|
|
177
|
+
fieldSelector?: string;
|
|
178
|
+
/** Get resources from all namespaces (-A) */
|
|
179
|
+
allNamespaces?: boolean;
|
|
180
|
+
/** jq filter expression to filter JSON output */
|
|
181
|
+
jqFilter?: string;
|
|
182
|
+
/** Enable watch mode (-w) - returns WatchProcess instead of data */
|
|
183
|
+
watch?: boolean;
|
|
184
|
+
/** Output format for watch mode (wide, name, custom-columns, etc.) */
|
|
185
|
+
output?: string;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Watch process controller
|
|
189
|
+
*/
|
|
190
|
+
export interface WatchProcess {
|
|
191
|
+
/** Interrupt the watch process (sends Ctrl+C) */
|
|
192
|
+
interrupt: () => Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Cluster information returned by clusterInfo
|
|
196
|
+
*/
|
|
197
|
+
export interface ClusterInfo {
|
|
198
|
+
/** Whether the cluster is reachable */
|
|
199
|
+
reachable: boolean;
|
|
200
|
+
/** Kubernetes control plane URL */
|
|
201
|
+
controlPlane?: string;
|
|
202
|
+
/** CoreDNS service URL */
|
|
203
|
+
coreDNS?: string;
|
|
204
|
+
/** Server version */
|
|
205
|
+
serverVersion?: string;
|
|
206
|
+
/** Error message if cluster is not reachable */
|
|
207
|
+
error?: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Kubectl plugin methods
|
|
211
|
+
*/
|
|
212
|
+
export interface KubectlMethods {
|
|
213
|
+
/** Run a kubectl command and return the output */
|
|
214
|
+
run: (args: string) => Promise<string>;
|
|
215
|
+
/** Get kubectl command prefix with namespace */
|
|
216
|
+
command: (args: string) => string;
|
|
217
|
+
/** Wait for a pod to be in a specific status */
|
|
218
|
+
waitForPod: (name: string, status?: 'Running' | 'Succeeded' | 'Failed' | 'Pending', timeout?: number) => Promise<void>;
|
|
219
|
+
/** Create a resource from a YAML string */
|
|
220
|
+
apply: (yaml: string) => Promise<ApplyResult>;
|
|
221
|
+
/** Delete a resource */
|
|
222
|
+
delete: (resource: string, name: string, options?: DeleteOptions) => Promise<DeleteResult>;
|
|
223
|
+
/** Get resource as JSON, supports label selector and other options */
|
|
224
|
+
get: {
|
|
225
|
+
<T = unknown>(resource: string, name?: string, options?: GetOptions & {
|
|
226
|
+
watch?: false | undefined;
|
|
227
|
+
}): Promise<T>;
|
|
228
|
+
(resource: string, name: string | undefined, options: GetOptions & {
|
|
229
|
+
watch: true;
|
|
230
|
+
}): Promise<WatchProcess>;
|
|
231
|
+
};
|
|
232
|
+
/** Get a specific field value using JSONPath expression */
|
|
233
|
+
getJsonPath: <T = string>(resource: string, name: string, jsonPath: string, options?: GetOptions) => Promise<T | undefined>;
|
|
234
|
+
/** Check if a resource exists */
|
|
235
|
+
exists: (resource: string, name: string) => Promise<boolean>;
|
|
236
|
+
/** Set the current namespace */
|
|
237
|
+
setNamespace: (namespace: string) => void;
|
|
238
|
+
/** Get the current namespace */
|
|
239
|
+
getNamespace: () => string;
|
|
240
|
+
/** Get the kubeconfig path */
|
|
241
|
+
getKubeconfig: () => string | undefined;
|
|
242
|
+
/** Return shell command to set KUBECONFIG (e.g. for use in terminal.run). Example: setCluster('/path/to/kubeconfig') => "export KUBECONFIG='/path/to/kubeconfig'" */
|
|
243
|
+
setCluster: (kubeConfigPath: string) => string;
|
|
244
|
+
/** Get cluster connection info */
|
|
245
|
+
clusterInfo: () => Promise<ClusterInfo>;
|
|
246
|
+
/** Get pod logs */
|
|
247
|
+
logs: (podName: string, options?: LogsOptions) => Promise<string>;
|
|
248
|
+
/** Execute command in pod */
|
|
249
|
+
exec: (podName: string, command: string | string[], options?: ExecOptions) => Promise<string>;
|
|
250
|
+
/** Get detailed resource description */
|
|
251
|
+
describe: (resource: string, name?: string) => Promise<string>;
|
|
252
|
+
/** Wait for a condition on a resource */
|
|
253
|
+
wait: (resource: string, name: string, condition: string, options?: WaitOptions) => Promise<WaitResult>;
|
|
254
|
+
/** Wait for a JSONPath field to have a specific value */
|
|
255
|
+
waitForJsonPath: (resource: string, name: string, jsonPath: string, value: string, timeout?: number) => Promise<void>;
|
|
256
|
+
/** Wait for resource to have specific replica count */
|
|
257
|
+
waitForReplicas: (resource: string, name: string, count: number, timeout?: number) => Promise<void>;
|
|
258
|
+
/** Scale a resource (Deployment, ReplicaSet, StatefulSet) */
|
|
259
|
+
scale: (resource: string, name: string, replicas: number) => Promise<ScaleResult>;
|
|
260
|
+
/** Patch a resource */
|
|
261
|
+
patch: (resource: string, name: string, patch: object | string, type?: 'strategic' | 'merge' | 'json') => Promise<PatchResult>;
|
|
262
|
+
/** Add or update labels on a resource */
|
|
263
|
+
label: (resource: string, name: string, labels: Record<string, string | null>) => Promise<LabelResult>;
|
|
264
|
+
/** Add or update annotations on a resource */
|
|
265
|
+
annotate: (resource: string, name: string, annotations: Record<string, string | null>) => Promise<LabelResult>;
|
|
266
|
+
/** Rollout management methods */
|
|
267
|
+
rollout: RolloutMethods;
|
|
268
|
+
/** Port forward to a resource */
|
|
269
|
+
portForward: (resource: string, ports: string, options?: PortForwardOptions) => Promise<PortForwardHandle>;
|
|
270
|
+
/** Wait for service to have endpoints */
|
|
271
|
+
waitForService: (name: string, timeout?: number) => Promise<ServiceEndpoint>;
|
|
272
|
+
/** Get cluster events */
|
|
273
|
+
getEvents: (options?: EventOptions) => Promise<K8sEvent[]>;
|
|
274
|
+
/** Get node information */
|
|
275
|
+
getNodes: (options?: {
|
|
276
|
+
selector?: string;
|
|
277
|
+
}) => Promise<NodeInfo[]>;
|
|
278
|
+
/** Copy files to/from pod */
|
|
279
|
+
cp: (source: string, dest: string, options?: CpOptions) => Promise<void>;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Plugin options
|
|
283
|
+
*/
|
|
284
|
+
export interface KubectlPluginOptions {
|
|
285
|
+
/** Default namespace */
|
|
286
|
+
namespace?: string;
|
|
287
|
+
/** Path to kubeconfig file */
|
|
288
|
+
kubeconfig?: string;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Create the kubectl plugin
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* import { defineConfig, createTestWithPlugins } from 'repterm';
|
|
296
|
+
* import { kubectlPlugin } from '@nexusgpu/repterm-plugin-kubectl';
|
|
297
|
+
*
|
|
298
|
+
* const config = defineConfig({
|
|
299
|
+
* plugins: [kubectlPlugin({ namespace: 'test' })] as const,
|
|
300
|
+
* });
|
|
301
|
+
*
|
|
302
|
+
* const test = createTestWithPlugins(config);
|
|
303
|
+
*
|
|
304
|
+
* test('deploy nginx', async (ctx) => {
|
|
305
|
+
* await ctx.plugins.kubectl.apply(`...`);
|
|
306
|
+
* await ctx.plugins.kubectl.waitForPod('nginx', 'Running');
|
|
307
|
+
* });
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
export declare function kubectlPlugin(options?: KubectlPluginOptions): import("repterm-api").PluginDefinition<"kubectl", BasePluginContext, KubectlContext, KubectlMethods>;
|
|
311
|
+
export declare const defaultKubectlPlugin: import("repterm-api").PluginDefinition<"kubectl", BasePluginContext, KubectlContext, KubectlMethods>;
|
|
312
|
+
export { K8sResource, pod, deployment, service, statefulset, job, configmap, secret, resource, gpupool, gpu, tensorfusionworkload, tensorfusionconnection, crd, registerK8sMatchers, } from './matchers.js';
|
|
313
|
+
export { KubectlResult, ApplyResult, DeleteResult, PatchResult, ScaleResult, LabelResult, } from './result.js';
|
|
314
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|