@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
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tensor Fusion GPU 资源分配测试 - 共享配置
|
|
3
|
+
*
|
|
4
|
+
* 运行方式:
|
|
5
|
+
* bun run repterm packages/plugin-kubectl/examples/tensor-fusion/
|
|
6
|
+
*
|
|
7
|
+
* 前置条件:
|
|
8
|
+
* - 已配置 kubectl 并连接到 Kubernetes 集群
|
|
9
|
+
* - Tensor Fusion Controller 已部署并运行
|
|
10
|
+
* - 至少存在一个 GPUPool 和可用 GPU
|
|
11
|
+
*/
|
|
12
|
+
import { describe, defineConfig, createTestWithPlugins, expect, step, } from 'repterm';
|
|
13
|
+
import { kubectlPlugin, gpupool, gpu, tensorfusionworkload, tensorfusionconnection, pod, deployment, resource, } from '../../src/index.js';
|
|
14
|
+
// ===== 常量配置 =====
|
|
15
|
+
/** 测试使用的 GPUPool 名称 */
|
|
16
|
+
export const TEST_GPU_POOL = 'tensor-fusion-shared';
|
|
17
|
+
/** 测试命名空间 */
|
|
18
|
+
export const TEST_NAMESPACE = 'default';
|
|
19
|
+
/** Tensor Fusion 系统命名空间 */
|
|
20
|
+
export const TF_SYSTEM_NAMESPACE = 'tensor-fusion-sys';
|
|
21
|
+
/** Controller Deployment 名称 */
|
|
22
|
+
export const TF_CONTROLLER_DEPLOYMENT = 'tensor-fusion-sys-controller';
|
|
23
|
+
/** 默认等待超时时间 (ms) */
|
|
24
|
+
export const DEFAULT_TIMEOUT = 60000;
|
|
25
|
+
// ===== 插件配置 =====
|
|
26
|
+
export const config = defineConfig({
|
|
27
|
+
plugins: [kubectlPlugin({ namespace: TEST_NAMESPACE })],
|
|
28
|
+
});
|
|
29
|
+
export const test = createTestWithPlugins(config);
|
|
30
|
+
// ===== 导出工具 =====
|
|
31
|
+
export { describe, expect, step, gpupool, gpu, tensorfusionworkload, tensorfusionconnection, pod, deployment, resource, };
|
|
32
|
+
// ===== YAML 模板 =====
|
|
33
|
+
/**
|
|
34
|
+
* TensorFusionWorkload 测试模板
|
|
35
|
+
*/
|
|
36
|
+
export const workloadYaml = (name, options = {}) => `
|
|
37
|
+
apiVersion: tensor-fusion.ai/v1
|
|
38
|
+
kind: TensorFusionWorkload
|
|
39
|
+
metadata:
|
|
40
|
+
name: ${name}
|
|
41
|
+
namespace: ${TEST_NAMESPACE}
|
|
42
|
+
labels:
|
|
43
|
+
app: ${name}
|
|
44
|
+
test-type: gpu-allocation
|
|
45
|
+
spec:
|
|
46
|
+
replicas: ${options.replicas ?? 1}
|
|
47
|
+
gpuCount: 1
|
|
48
|
+
poolName: ${options.poolName ?? TEST_GPU_POOL}
|
|
49
|
+
qos: medium
|
|
50
|
+
isolation: soft
|
|
51
|
+
resources:
|
|
52
|
+
requests:
|
|
53
|
+
tflops: ${options.tflopsRequest ?? '1000m'}
|
|
54
|
+
vram: "${options.vramRequest ?? '1Gi'}"
|
|
55
|
+
limits:
|
|
56
|
+
tflops: ${options.tflopsLimit ?? '2000m'}
|
|
57
|
+
vram: "${options.vramLimit ?? '2Gi'}"
|
|
58
|
+
isLocalGPU: true
|
|
59
|
+
gpuIndices:
|
|
60
|
+
- 0
|
|
61
|
+
autoScalingConfig:
|
|
62
|
+
autoSetResources:
|
|
63
|
+
enable: false
|
|
64
|
+
`;
|
|
65
|
+
/**
|
|
66
|
+
* 带 Tensor Fusion Annotation 的 Deployment 模板
|
|
67
|
+
*/
|
|
68
|
+
export const annotatedDeploymentYaml = (name, options = {}) => `
|
|
69
|
+
apiVersion: apps/v1
|
|
70
|
+
kind: Deployment
|
|
71
|
+
metadata:
|
|
72
|
+
name: ${name}
|
|
73
|
+
namespace: ${TEST_NAMESPACE}
|
|
74
|
+
labels:
|
|
75
|
+
app: ${name}
|
|
76
|
+
spec:
|
|
77
|
+
replicas: 1
|
|
78
|
+
selector:
|
|
79
|
+
matchLabels:
|
|
80
|
+
app: ${name}
|
|
81
|
+
template:
|
|
82
|
+
metadata:
|
|
83
|
+
labels:
|
|
84
|
+
app: ${name}
|
|
85
|
+
annotations:
|
|
86
|
+
tensor-fusion.ai/gpu-pool: "${options.poolName ?? TEST_GPU_POOL}"
|
|
87
|
+
tensor-fusion.ai/gpu-count: "1"
|
|
88
|
+
tensor-fusion.ai/tflops-request: "${options.tflopsRequest ?? '1000m'}"
|
|
89
|
+
tensor-fusion.ai/tflops-limit: "${options.tflopsLimit ?? '2000m'}"
|
|
90
|
+
tensor-fusion.ai/vram-request: "${options.vramRequest ?? '1Gi'}"
|
|
91
|
+
tensor-fusion.ai/vram-limit: "${options.vramLimit ?? '2Gi'}"
|
|
92
|
+
tensor-fusion.ai/qos: "medium"
|
|
93
|
+
tensor-fusion.ai/isolation: "soft"
|
|
94
|
+
tensor-fusion.ai/is-local-gpu: "true"
|
|
95
|
+
tensor-fusion.ai/gpu-indices: "0"
|
|
96
|
+
spec:
|
|
97
|
+
containers:
|
|
98
|
+
- name: test-container
|
|
99
|
+
image: nginx:alpine
|
|
100
|
+
command: ["sleep", "infinity"]
|
|
101
|
+
resources:
|
|
102
|
+
requests:
|
|
103
|
+
memory: "256Mi"
|
|
104
|
+
cpu: "100m"
|
|
105
|
+
limits:
|
|
106
|
+
memory: "512Mi"
|
|
107
|
+
cpu: "500m"
|
|
108
|
+
`;
|
|
109
|
+
// ===== 工具函数 =====
|
|
110
|
+
/**
|
|
111
|
+
* 获取 GPUPool 中第一个 GPU 名称
|
|
112
|
+
*/
|
|
113
|
+
export async function getFirstGpuName(kubectl) {
|
|
114
|
+
// 使用 jq 过滤出第一个 NVIDIA GPU 的名称
|
|
115
|
+
const result = await kubectl.get('gpu', '', {
|
|
116
|
+
selector: `tensor-fusion.ai/gpupool=${TEST_GPU_POOL}`,
|
|
117
|
+
jqFilter: '[.items[] | select(.status.vendor | ascii_downcase == "nvidia")][0] | .metadata.name'
|
|
118
|
+
});
|
|
119
|
+
const gpuName = typeof result === 'string' ? result.trim() : '';
|
|
120
|
+
if (!gpuName) {
|
|
121
|
+
throw new Error(`No NVIDIA GPU found in pool ${TEST_GPU_POOL}`);
|
|
122
|
+
}
|
|
123
|
+
return gpuName;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 获取 GPU 的可用资源
|
|
127
|
+
*/
|
|
128
|
+
export async function getGpuAvailable(kubectl, gpuName) {
|
|
129
|
+
const available = await kubectl.getJsonPath('gpu', gpuName, '.status.available');
|
|
130
|
+
return {
|
|
131
|
+
tflops: String(available?.tflops ?? '0'),
|
|
132
|
+
vram: String(available?.vram ?? '0'),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 解析 TFlops 值为数字(支持带 m 后缀和不带后缀的格式)
|
|
137
|
+
*/
|
|
138
|
+
export function parseTflops(value) {
|
|
139
|
+
const str = String(value);
|
|
140
|
+
if (str.endsWith('m')) {
|
|
141
|
+
return parseInt(str.replace('m', ''), 10);
|
|
142
|
+
}
|
|
143
|
+
// 如果没有 m 后缀,假设单位是 TFlops,转换为 milli
|
|
144
|
+
const num = parseFloat(str);
|
|
145
|
+
return isNaN(num) ? 0 : num * 1000;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 清理测试资源
|
|
149
|
+
*/
|
|
150
|
+
export async function cleanup(kubectl, resources) {
|
|
151
|
+
for (const { kind, name } of resources) {
|
|
152
|
+
try {
|
|
153
|
+
await kubectl.delete(kind, name);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// 忽略删除错误
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -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/plugin-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 进程控制器
|
|
189
|
+
*/
|
|
190
|
+
export interface WatchProcess {
|
|
191
|
+
/** 中断 watch 进程 (发送 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 '@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").PluginDefinition<"kubectl", BasePluginContext, KubectlContext, KubectlMethods>;
|
|
311
|
+
export declare const defaultKubectlPlugin: import("repterm").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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"}
|