@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.
Files changed (101) hide show
  1. package/README.md +277 -0
  2. package/dist/index.d.ts +314 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +544 -0
  5. package/dist/matchers.d.ts +113 -0
  6. package/dist/matchers.d.ts.map +1 -0
  7. package/dist/matchers.js +527 -0
  8. package/dist/plugin-kubectl/examples/00-simple-demo.d.ts +10 -0
  9. package/dist/plugin-kubectl/examples/00-simple-demo.d.ts.map +1 -0
  10. package/dist/plugin-kubectl/examples/00-simple-demo.js +51 -0
  11. package/dist/plugin-kubectl/examples/01-basic-kubectl.d.ts +13 -0
  12. package/dist/plugin-kubectl/examples/01-basic-kubectl.d.ts.map +1 -0
  13. package/dist/plugin-kubectl/examples/01-basic-kubectl.js +86 -0
  14. package/dist/plugin-kubectl/examples/02-debugging.d.ts +13 -0
  15. package/dist/plugin-kubectl/examples/02-debugging.d.ts.map +1 -0
  16. package/dist/plugin-kubectl/examples/02-debugging.js +80 -0
  17. package/dist/plugin-kubectl/examples/03-resource-management.d.ts +13 -0
  18. package/dist/plugin-kubectl/examples/03-resource-management.d.ts.map +1 -0
  19. package/dist/plugin-kubectl/examples/03-resource-management.js +134 -0
  20. package/dist/plugin-kubectl/examples/04-rollout.d.ts +13 -0
  21. package/dist/plugin-kubectl/examples/04-rollout.d.ts.map +1 -0
  22. package/dist/plugin-kubectl/examples/04-rollout.js +122 -0
  23. package/dist/plugin-kubectl/examples/05-matchers.d.ts +15 -0
  24. package/dist/plugin-kubectl/examples/05-matchers.d.ts.map +1 -0
  25. package/dist/plugin-kubectl/examples/05-matchers.js +138 -0
  26. package/dist/plugin-kubectl/examples/06-advanced.d.ts +14 -0
  27. package/dist/plugin-kubectl/examples/06-advanced.d.ts.map +1 -0
  28. package/dist/plugin-kubectl/examples/06-advanced.js +140 -0
  29. package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.d.ts +14 -0
  30. package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.d.ts.map +1 -0
  31. package/dist/plugin-kubectl/examples/tensor-fusion/00-prerequisites.js +66 -0
  32. package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.d.ts +14 -0
  33. package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.d.ts.map +1 -0
  34. package/dist/plugin-kubectl/examples/tensor-fusion/01-workload-allocation.js +145 -0
  35. package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.d.ts +13 -0
  36. package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.d.ts.map +1 -0
  37. package/dist/plugin-kubectl/examples/tensor-fusion/02-annotation-mode.js +123 -0
  38. package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.d.ts +17 -0
  39. package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.d.ts.map +1 -0
  40. package/dist/plugin-kubectl/examples/tensor-fusion/03-insufficient.js +96 -0
  41. package/dist/plugin-kubectl/examples/tensor-fusion/04-release.d.ts +13 -0
  42. package/dist/plugin-kubectl/examples/tensor-fusion/04-release.d.ts.map +1 -0
  43. package/dist/plugin-kubectl/examples/tensor-fusion/04-release.js +117 -0
  44. package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.d.ts +14 -0
  45. package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.d.ts.map +1 -0
  46. package/dist/plugin-kubectl/examples/tensor-fusion/05-multi-workload-shared-gpu.js +145 -0
  47. package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.d.ts +14 -0
  48. package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.d.ts.map +1 -0
  49. package/dist/plugin-kubectl/examples/tensor-fusion/06-workload-resource-resize.js +235 -0
  50. package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.d.ts +15 -0
  51. package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.d.ts.map +1 -0
  52. package/dist/plugin-kubectl/examples/tensor-fusion/07-workload-worker-pod-generation.js +146 -0
  53. package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.d.ts +13 -0
  54. package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.d.ts.map +1 -0
  55. package/dist/plugin-kubectl/examples/tensor-fusion/08-workload-replicas-scale.js +141 -0
  56. package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.d.ts +15 -0
  57. package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.d.ts.map +1 -0
  58. package/dist/plugin-kubectl/examples/tensor-fusion/09-gpu-remote-invocation.js +256 -0
  59. package/dist/plugin-kubectl/examples/tensor-fusion/_config.d.ts +71 -0
  60. package/dist/plugin-kubectl/examples/tensor-fusion/_config.d.ts.map +1 -0
  61. package/dist/plugin-kubectl/examples/tensor-fusion/_config.js +159 -0
  62. package/dist/plugin-kubectl/src/index.d.ts +314 -0
  63. package/dist/plugin-kubectl/src/index.d.ts.map +1 -0
  64. package/dist/plugin-kubectl/src/index.js +545 -0
  65. package/dist/plugin-kubectl/src/matchers.d.ts +113 -0
  66. package/dist/plugin-kubectl/src/matchers.d.ts.map +1 -0
  67. package/dist/plugin-kubectl/src/matchers.js +527 -0
  68. package/dist/plugin-kubectl/src/result.d.ts +80 -0
  69. package/dist/plugin-kubectl/src/result.d.ts.map +1 -0
  70. package/dist/plugin-kubectl/src/result.js +134 -0
  71. package/dist/repterm/src/api/describe.d.ts +18 -0
  72. package/dist/repterm/src/api/describe.d.ts.map +1 -0
  73. package/dist/repterm/src/api/describe.js +32 -0
  74. package/dist/repterm/src/api/expect.d.ts +43 -0
  75. package/dist/repterm/src/api/expect.d.ts.map +1 -0
  76. package/dist/repterm/src/api/expect.js +166 -0
  77. package/dist/repterm/src/api/hooks.d.ts +178 -0
  78. package/dist/repterm/src/api/hooks.d.ts.map +1 -0
  79. package/dist/repterm/src/api/hooks.js +230 -0
  80. package/dist/repterm/src/api/steps.d.ts +45 -0
  81. package/dist/repterm/src/api/steps.d.ts.map +1 -0
  82. package/dist/repterm/src/api/steps.js +105 -0
  83. package/dist/repterm/src/api/test.d.ts +101 -0
  84. package/dist/repterm/src/api/test.d.ts.map +1 -0
  85. package/dist/repterm/src/api/test.js +206 -0
  86. package/dist/repterm/src/index.d.ts +15 -0
  87. package/dist/repterm/src/index.d.ts.map +1 -0
  88. package/dist/repterm/src/index.js +23 -0
  89. package/dist/repterm/src/plugin/index.d.ts +47 -0
  90. package/dist/repterm/src/plugin/index.d.ts.map +1 -0
  91. package/dist/repterm/src/plugin/index.js +85 -0
  92. package/dist/repterm/src/plugin/withPlugins.d.ts +71 -0
  93. package/dist/repterm/src/plugin/withPlugins.d.ts.map +1 -0
  94. package/dist/repterm/src/plugin/withPlugins.js +100 -0
  95. package/dist/repterm/src/runner/models.d.ts +261 -0
  96. package/dist/repterm/src/runner/models.d.ts.map +1 -0
  97. package/dist/repterm/src/runner/models.js +4 -0
  98. package/dist/result.d.ts +80 -0
  99. package/dist/result.d.ts.map +1 -0
  100. package/dist/result.js +134 -0
  101. 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
@@ -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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"}