@blogic-cz/agent-tools 0.16.0 → 0.17.1
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/dist/audit-tool/index.d.ts +3 -0
- package/dist/audit-tool/index.d.ts.map +1 -0
- package/dist/az-tool/build.d.ts +47 -0
- package/dist/az-tool/build.d.ts.map +1 -0
- package/dist/az-tool/config.d.ts +13 -0
- package/dist/az-tool/config.d.ts.map +1 -0
- package/dist/az-tool/errors.d.ts +43 -0
- package/dist/az-tool/errors.d.ts.map +1 -0
- package/dist/az-tool/extract-option-value.d.ts +2 -0
- package/dist/az-tool/extract-option-value.d.ts.map +1 -0
- package/dist/az-tool/index.d.ts +3 -0
- package/dist/az-tool/index.d.ts.map +1 -0
- package/dist/az-tool/security.d.ts +4 -0
- package/dist/az-tool/security.d.ts.map +1 -0
- package/dist/az-tool/service.d.ts +15 -0
- package/dist/az-tool/service.d.ts.map +1 -0
- package/dist/az-tool/transformers.d.ts +10 -0
- package/dist/az-tool/transformers.d.ts.map +1 -0
- package/dist/az-tool/types.d.ts +64 -0
- package/dist/az-tool/types.d.ts.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/loader.d.ts +22 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/types.d.ts +189 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/credential-guard/claude-hook.d.ts +13 -0
- package/dist/credential-guard/claude-hook.d.ts.map +1 -0
- package/dist/credential-guard/index.d.ts +77 -0
- package/dist/credential-guard/index.d.ts.map +1 -0
- package/dist/db-tool/config-service.d.ts +25 -0
- package/dist/db-tool/config-service.d.ts.map +1 -0
- package/dist/db-tool/errors.d.ts +41 -0
- package/dist/db-tool/errors.d.ts.map +1 -0
- package/dist/db-tool/index.d.ts +3 -0
- package/dist/db-tool/index.d.ts.map +1 -0
- package/dist/db-tool/schema.d.ts +21 -0
- package/dist/db-tool/schema.d.ts.map +1 -0
- package/dist/db-tool/security.d.ts +23 -0
- package/dist/db-tool/security.d.ts.map +1 -0
- package/dist/db-tool/service.d.ts +18 -0
- package/dist/db-tool/service.d.ts.map +1 -0
- package/dist/db-tool/sql-client.d.ts +24 -0
- package/dist/db-tool/sql-client.d.ts.map +1 -0
- package/dist/db-tool/transformers.d.ts +10 -0
- package/dist/db-tool/transformers.d.ts.map +1 -0
- package/dist/db-tool/types.d.ts +37 -0
- package/dist/db-tool/types.d.ts.map +1 -0
- package/dist/gh-tool/branch.d.ts +18 -0
- package/dist/gh-tool/branch.d.ts.map +1 -0
- package/dist/gh-tool/config.d.ts +7 -0
- package/dist/gh-tool/config.d.ts.map +1 -0
- package/dist/gh-tool/errors.d.ts +51 -0
- package/dist/gh-tool/errors.d.ts.map +1 -0
- package/dist/gh-tool/index.d.ts +3 -0
- package/dist/gh-tool/index.d.ts.map +1 -0
- package/dist/gh-tool/issue/commands.d.ts +68 -0
- package/dist/gh-tool/issue/commands.d.ts.map +1 -0
- package/dist/gh-tool/issue/core.d.ts +82 -0
- package/dist/gh-tool/issue/core.d.ts.map +1 -0
- package/dist/gh-tool/issue/index.d.ts +3 -0
- package/dist/gh-tool/issue/index.d.ts.map +1 -0
- package/dist/gh-tool/issue/triage.d.ts +89 -0
- package/dist/gh-tool/issue/triage.d.ts.map +1 -0
- package/dist/gh-tool/pr/commands.d.ts +384 -0
- package/dist/gh-tool/pr/commands.d.ts.map +1 -0
- package/dist/gh-tool/pr/core.d.ts +236 -0
- package/dist/gh-tool/pr/core.d.ts.map +1 -0
- package/dist/gh-tool/pr/helpers.d.ts +27 -0
- package/dist/gh-tool/pr/helpers.d.ts.map +1 -0
- package/dist/gh-tool/pr/index.d.ts +2 -0
- package/dist/gh-tool/pr/index.d.ts.map +1 -0
- package/dist/gh-tool/pr/review.d.ts +90 -0
- package/dist/gh-tool/pr/review.d.ts.map +1 -0
- package/dist/gh-tool/release.d.ts +52 -0
- package/dist/gh-tool/release.d.ts.map +1 -0
- package/dist/gh-tool/repo.d.ts +21 -0
- package/dist/gh-tool/repo.d.ts.map +1 -0
- package/dist/gh-tool/service.d.ts +25 -0
- package/dist/gh-tool/service.d.ts.map +1 -0
- package/dist/gh-tool/text-input.d.ts +22 -0
- package/dist/gh-tool/text-input.d.ts.map +1 -0
- package/dist/gh-tool/types.d.ts +271 -0
- package/dist/gh-tool/types.d.ts.map +1 -0
- package/dist/gh-tool/workflow.d.ts +157 -0
- package/dist/gh-tool/workflow.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/k8s-tool/context.d.ts +26 -0
- package/dist/k8s-tool/context.d.ts.map +1 -0
- package/dist/k8s-tool/errors.d.ts +43 -0
- package/dist/k8s-tool/errors.d.ts.map +1 -0
- package/dist/k8s-tool/index.d.ts +3 -0
- package/dist/k8s-tool/index.d.ts.map +1 -0
- package/dist/k8s-tool/profile.d.ts +3 -0
- package/dist/k8s-tool/profile.d.ts.map +1 -0
- package/dist/k8s-tool/security.d.ts +14 -0
- package/dist/k8s-tool/security.d.ts.map +1 -0
- package/dist/k8s-tool/service.d.ts +16 -0
- package/dist/k8s-tool/service.d.ts.map +1 -0
- package/dist/k8s-tool/transformers.d.ts +23 -0
- package/dist/k8s-tool/transformers.d.ts.map +1 -0
- package/dist/k8s-tool/types.d.ts +13 -0
- package/dist/k8s-tool/types.d.ts.map +1 -0
- package/dist/logs-tool/errors.d.ts +40 -0
- package/dist/logs-tool/errors.d.ts.map +1 -0
- package/dist/logs-tool/index.d.ts +21 -0
- package/dist/logs-tool/index.d.ts.map +1 -0
- package/dist/logs-tool/service.d.ts +17 -0
- package/dist/logs-tool/service.d.ts.map +1 -0
- package/dist/logs-tool/transformers.d.ts +2 -0
- package/dist/logs-tool/transformers.d.ts.map +1 -0
- package/dist/logs-tool/types.d.ts +39 -0
- package/dist/logs-tool/types.d.ts.map +1 -0
- package/dist/observability-tool/errors.d.ts +8 -0
- package/dist/observability-tool/errors.d.ts.map +1 -0
- package/dist/observability-tool/index.d.ts +3 -0
- package/dist/observability-tool/index.d.ts.map +1 -0
- package/dist/observability-tool/logs.d.ts +22 -0
- package/dist/observability-tool/logs.d.ts.map +1 -0
- package/dist/observability-tool/metrics.d.ts +3 -0
- package/dist/observability-tool/metrics.d.ts.map +1 -0
- package/dist/observability-tool/shared.d.ts +18 -0
- package/dist/observability-tool/shared.d.ts.map +1 -0
- package/dist/observability-tool/trace.d.ts +3 -0
- package/dist/observability-tool/trace.d.ts.map +1 -0
- package/dist/observability-tool/types.d.ts +171 -0
- package/dist/observability-tool/types.d.ts.map +1 -0
- package/dist/session-tool/claude-code.d.ts +46 -0
- package/dist/session-tool/claude-code.d.ts.map +1 -0
- package/dist/session-tool/codex.d.ts +44 -0
- package/dist/session-tool/codex.d.ts.map +1 -0
- package/dist/session-tool/config.d.ts +29 -0
- package/dist/session-tool/config.d.ts.map +1 -0
- package/dist/session-tool/errors.d.ts +27 -0
- package/dist/session-tool/errors.d.ts.map +1 -0
- package/dist/session-tool/index.d.ts +13 -0
- package/dist/session-tool/index.d.ts.map +1 -0
- package/dist/session-tool/pi.d.ts +40 -0
- package/dist/session-tool/pi.d.ts.map +1 -0
- package/dist/session-tool/service.d.ts +18 -0
- package/dist/session-tool/service.d.ts.map +1 -0
- package/dist/session-tool/summaries.d.ts +5 -0
- package/dist/session-tool/summaries.d.ts.map +1 -0
- package/dist/session-tool/types.d.ts +38 -0
- package/dist/session-tool/types.d.ts.map +1 -0
- package/dist/shared/audit.d.ts +40 -0
- package/dist/shared/audit.d.ts.map +1 -0
- package/dist/shared/binary-preflight.d.ts +27 -0
- package/dist/shared/binary-preflight.d.ts.map +1 -0
- package/dist/shared/bun.d.ts +4 -0
- package/dist/shared/bun.d.ts.map +1 -0
- package/dist/shared/cli.d.ts +18 -0
- package/dist/shared/cli.d.ts.map +1 -0
- package/dist/shared/env-template.d.ts +9 -0
- package/dist/shared/env-template.d.ts.map +1 -0
- package/dist/shared/error-renderer.d.ts +4 -0
- package/dist/shared/error-renderer.d.ts.map +1 -0
- package/dist/shared/exec.d.ts +30 -0
- package/dist/shared/exec.d.ts.map +1 -0
- package/dist/shared/format.d.ts +7 -0
- package/dist/shared/format.d.ts.map +1 -0
- package/dist/shared/index.d.ts +12 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/k8s-probe.d.ts +11 -0
- package/dist/shared/k8s-probe.d.ts.map +1 -0
- package/dist/shared/log-transform.d.ts +2 -0
- package/dist/shared/log-transform.d.ts.map +1 -0
- package/dist/shared/path.d.ts +2 -0
- package/dist/shared/path.d.ts.map +1 -0
- package/dist/shared/prerequisites/config.d.ts +6 -0
- package/dist/shared/prerequisites/config.d.ts.map +1 -0
- package/dist/shared/prerequisites/driver-commands.d.ts +19 -0
- package/dist/shared/prerequisites/driver-commands.d.ts.map +1 -0
- package/dist/shared/prerequisites/errors.d.ts +10 -0
- package/dist/shared/prerequisites/errors.d.ts.map +1 -0
- package/dist/shared/prerequisites/guardian-entry.d.ts +2 -0
- package/dist/shared/prerequisites/guardian-entry.d.ts.map +1 -0
- package/dist/shared/prerequisites/guardian.d.ts +41 -0
- package/dist/shared/prerequisites/guardian.d.ts.map +1 -0
- package/dist/shared/prerequisites/index.d.ts +6 -0
- package/dist/shared/prerequisites/index.d.ts.map +1 -0
- package/dist/shared/prerequisites/runtime.d.ts +26 -0
- package/dist/shared/prerequisites/runtime.d.ts.map +1 -0
- package/dist/shared/prerequisites/store.d.ts +99 -0
- package/dist/shared/prerequisites/store.d.ts.map +1 -0
- package/dist/shared/prerequisites/types.d.ts +39 -0
- package/dist/shared/prerequisites/types.d.ts.map +1 -0
- package/dist/shared/prerequisites/vpn.d.ts +5 -0
- package/dist/shared/prerequisites/vpn.d.ts.map +1 -0
- package/dist/shared/schema-dump.d.ts +27 -0
- package/dist/shared/schema-dump.d.ts.map +1 -0
- package/dist/shared/throttle.d.ts +17 -0
- package/dist/shared/throttle.d.ts.map +1 -0
- package/dist/shared/transform.d.ts +49 -0
- package/dist/shared/transform.d.ts.map +1 -0
- package/dist/shared/types.d.ts +30 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/package.json +77 -20
- package/src/az-tool/service.ts +30 -23
- package/src/k8s-tool/context.ts +73 -0
- package/src/k8s-tool/service.ts +34 -62
- package/src/logs-tool/service.ts +78 -87
- package/src/shared/bun.ts +0 -7
- package/src/shared/exec.ts +58 -4
- package/src/shared/index.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blogic-cz/agent-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "CLI tools for AI coding agent workflows — GitHub, database, Kubernetes, Azure DevOps, logs, sessions, and audit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -38,34 +38,89 @@
|
|
|
38
38
|
"session-tool": "./src/session-tool/index.ts"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
|
+
"dist/",
|
|
41
42
|
"src/",
|
|
42
43
|
"schemas/",
|
|
43
44
|
"README.md",
|
|
44
45
|
"LICENSE"
|
|
45
46
|
],
|
|
46
47
|
"type": "module",
|
|
47
|
-
"types": "./
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
48
49
|
"imports": {
|
|
49
|
-
"#shared":
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"#
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"#
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
"#shared": {
|
|
51
|
+
"types": "./dist/shared/index.d.ts",
|
|
52
|
+
"default": "./src/shared/index.ts"
|
|
53
|
+
},
|
|
54
|
+
"#shared/*": {
|
|
55
|
+
"types": "./dist/shared/*.d.ts",
|
|
56
|
+
"default": "./src/shared/*.ts"
|
|
57
|
+
},
|
|
58
|
+
"#config": {
|
|
59
|
+
"types": "./dist/config/index.d.ts",
|
|
60
|
+
"default": "./src/config/index.ts"
|
|
61
|
+
},
|
|
62
|
+
"#config/*": {
|
|
63
|
+
"types": "./dist/config/*.d.ts",
|
|
64
|
+
"default": "./src/config/*.ts"
|
|
65
|
+
},
|
|
66
|
+
"#gh/*": {
|
|
67
|
+
"types": "./dist/gh-tool/*.d.ts",
|
|
68
|
+
"default": "./src/gh-tool/*.ts"
|
|
69
|
+
},
|
|
70
|
+
"#k8s/*": {
|
|
71
|
+
"types": "./dist/k8s-tool/*.d.ts",
|
|
72
|
+
"default": "./src/k8s-tool/*.ts"
|
|
73
|
+
},
|
|
74
|
+
"#db/*": {
|
|
75
|
+
"types": "./dist/db-tool/*.d.ts",
|
|
76
|
+
"default": "./src/db-tool/*.ts"
|
|
77
|
+
},
|
|
78
|
+
"#observability/*": {
|
|
79
|
+
"types": "./dist/observability-tool/*.d.ts",
|
|
80
|
+
"default": "./src/observability-tool/*.ts"
|
|
81
|
+
},
|
|
82
|
+
"#logs/*": {
|
|
83
|
+
"types": "./dist/logs-tool/*.d.ts",
|
|
84
|
+
"default": "./src/logs-tool/*.ts"
|
|
85
|
+
},
|
|
86
|
+
"#az/*": {
|
|
87
|
+
"types": "./dist/az-tool/*.d.ts",
|
|
88
|
+
"default": "./src/az-tool/*.ts"
|
|
89
|
+
},
|
|
90
|
+
"#guard": {
|
|
91
|
+
"types": "./dist/credential-guard/index.d.ts",
|
|
92
|
+
"default": "./src/credential-guard/index.ts"
|
|
93
|
+
},
|
|
94
|
+
"#session/*": {
|
|
95
|
+
"types": "./dist/session-tool/*.d.ts",
|
|
96
|
+
"default": "./src/session-tool/*.ts"
|
|
97
|
+
}
|
|
61
98
|
},
|
|
62
99
|
"exports": {
|
|
63
|
-
".":
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"./
|
|
68
|
-
|
|
100
|
+
".": {
|
|
101
|
+
"types": "./dist/index.d.ts",
|
|
102
|
+
"default": "./src/index.ts"
|
|
103
|
+
},
|
|
104
|
+
"./credential-guard": {
|
|
105
|
+
"types": "./dist/credential-guard/index.d.ts",
|
|
106
|
+
"default": "./src/credential-guard/index.ts"
|
|
107
|
+
},
|
|
108
|
+
"./config": {
|
|
109
|
+
"types": "./dist/config/index.d.ts",
|
|
110
|
+
"default": "./src/config/index.ts"
|
|
111
|
+
},
|
|
112
|
+
"./audit": {
|
|
113
|
+
"types": "./dist/shared/audit.d.ts",
|
|
114
|
+
"default": "./src/shared/audit.ts"
|
|
115
|
+
},
|
|
116
|
+
"./k8s-probe": {
|
|
117
|
+
"types": "./dist/shared/k8s-probe.d.ts",
|
|
118
|
+
"default": "./src/shared/k8s-probe.ts"
|
|
119
|
+
},
|
|
120
|
+
"./prerequisites": {
|
|
121
|
+
"types": "./dist/shared/prerequisites/index.d.ts",
|
|
122
|
+
"default": "./src/shared/prerequisites/index.ts"
|
|
123
|
+
}
|
|
69
124
|
},
|
|
70
125
|
"publishConfig": {
|
|
71
126
|
"access": "public"
|
|
@@ -73,6 +128,8 @@
|
|
|
73
128
|
"scripts": {
|
|
74
129
|
"check": "bun check.ts",
|
|
75
130
|
"check:ci": "bun check.ts ci",
|
|
131
|
+
"build:types": "tsc -p tsconfig.declarations.json",
|
|
132
|
+
"prepare": "bun run build:types",
|
|
76
133
|
"format": "oxfmt",
|
|
77
134
|
"format:check": "oxfmt --check",
|
|
78
135
|
"observability-tool": "bun src/observability-tool/index.ts",
|
package/src/az-tool/service.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { AzSecurityError, AzCommandError, AzTimeoutError, AzParseError } from ".
|
|
|
9
9
|
import { isCommandAllowed, isInvokeAllowed } from "./security";
|
|
10
10
|
import { transformCmdOutput } from "./transformers";
|
|
11
11
|
import { ConfigService, getToolConfig } from "#config";
|
|
12
|
+
import { renderCommandLine, tokenizeCommandLine } from "#shared/exec";
|
|
12
13
|
|
|
13
14
|
export class AzService extends Context.Service<
|
|
14
15
|
AzService,
|
|
@@ -43,10 +44,10 @@ export class AzService extends Context.Service<
|
|
|
43
44
|
|
|
44
45
|
const executor = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
45
46
|
|
|
46
|
-
const
|
|
47
|
+
const runAzCommand = (argv: readonly string[], timeoutMs: number) =>
|
|
47
48
|
Effect.scoped(
|
|
48
49
|
Effect.gen(function* () {
|
|
49
|
-
const command = ChildProcess.make("
|
|
50
|
+
const command = ChildProcess.make("az", argv, {
|
|
50
51
|
stdout: "pipe",
|
|
51
52
|
stderr: "pipe",
|
|
52
53
|
});
|
|
@@ -68,7 +69,7 @@ export class AzService extends Context.Service<
|
|
|
68
69
|
(platformError) =>
|
|
69
70
|
new AzCommandError({
|
|
70
71
|
message: `Command execution failed: ${platformError.message}`,
|
|
71
|
-
command:
|
|
72
|
+
command: renderCommandLine(["az", ...argv]),
|
|
72
73
|
exitCode: -1,
|
|
73
74
|
hint: "Check that the az CLI is installed and authenticated",
|
|
74
75
|
nextCommand: "az login",
|
|
@@ -112,17 +113,22 @@ export class AzService extends Context.Service<
|
|
|
112
113
|
firstWord as (typeof STANDALONE_AZ_COMMANDS)[number],
|
|
113
114
|
);
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
const cmdArgv = tokenizeCommandLine(cmd);
|
|
117
|
+
const scopeArgv = [
|
|
118
|
+
"--organization",
|
|
119
|
+
azConfig.organization,
|
|
120
|
+
"--project",
|
|
121
|
+
projectName,
|
|
122
|
+
] as const;
|
|
116
123
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
fullCommand = `az devops ${cmd} --organization "${azConfig.organization}" --project "${projectName}"`;
|
|
123
|
-
}
|
|
124
|
+
const argv = isStandaloneCommand
|
|
125
|
+
? cmdArgv
|
|
126
|
+
: isDirectCommand
|
|
127
|
+
? [...cmdArgv, ...scopeArgv]
|
|
128
|
+
: ["devops", ...cmdArgv, ...scopeArgv];
|
|
124
129
|
|
|
125
|
-
const
|
|
130
|
+
const fullCommand = renderCommandLine(["az", ...argv]);
|
|
131
|
+
const resultOption = yield* runAzCommand(argv, azConfig.timeoutMs ?? 60000);
|
|
126
132
|
|
|
127
133
|
if (Option.isNone(resultOption)) {
|
|
128
134
|
return yield* new AzTimeoutError({
|
|
@@ -165,7 +171,7 @@ export class AzService extends Context.Service<
|
|
|
165
171
|
});
|
|
166
172
|
}
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
const argv = ["devops", "invoke", "--area", params.area, "--resource", params.resource];
|
|
169
175
|
|
|
170
176
|
const projectName = resolveProject(params.project);
|
|
171
177
|
|
|
@@ -175,22 +181,23 @@ export class AzService extends Context.Service<
|
|
|
175
181
|
};
|
|
176
182
|
|
|
177
183
|
if (Object.keys(routeParameters).length > 0) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
.
|
|
181
|
-
|
|
184
|
+
argv.push(
|
|
185
|
+
"--route-parameters",
|
|
186
|
+
...Object.entries(routeParameters).map(([k, v]) => `${k}=${v}`),
|
|
187
|
+
);
|
|
182
188
|
}
|
|
183
189
|
|
|
184
190
|
if (params.queryParameters) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
.
|
|
188
|
-
|
|
191
|
+
argv.push(
|
|
192
|
+
"--query-parameters",
|
|
193
|
+
...Object.entries(params.queryParameters).map(([k, v]) => `${k}=${v}`),
|
|
194
|
+
);
|
|
189
195
|
}
|
|
190
196
|
|
|
191
|
-
|
|
197
|
+
argv.push("--organization", azConfig.organization, "--output", "json");
|
|
192
198
|
|
|
193
|
-
const
|
|
199
|
+
const fullCommand = renderCommandLine(["az", ...argv]);
|
|
200
|
+
const resultOption = yield* runAzCommand(argv, azConfig.timeoutMs ?? 60000);
|
|
194
201
|
|
|
195
202
|
if (Option.isNone(resultOption)) {
|
|
196
203
|
return yield* new AzTimeoutError({
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Kept free of I/O so the caller spawns kubectl itself instead of piping through sh, jq and head. */
|
|
2
|
+
|
|
3
|
+
type KubeContextEntry = {
|
|
4
|
+
readonly name?: unknown;
|
|
5
|
+
readonly context?: { readonly cluster?: unknown };
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type KubeClusterEntry = {
|
|
9
|
+
readonly name?: unknown;
|
|
10
|
+
readonly cluster?: { readonly server?: unknown };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type KubeConfigView = {
|
|
14
|
+
readonly contexts?: readonly KubeContextEntry[];
|
|
15
|
+
readonly clusters?: readonly KubeClusterEntry[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const asString = (value: unknown): string | undefined =>
|
|
19
|
+
typeof value === "string" && value !== "" ? value : undefined;
|
|
20
|
+
|
|
21
|
+
export const parseKubeConfigView = (stdout: string): KubeConfigView | undefined => {
|
|
22
|
+
try {
|
|
23
|
+
const parsed: unknown = JSON.parse(stdout);
|
|
24
|
+
return typeof parsed === "object" && parsed !== null ? (parsed as KubeConfigView) : undefined;
|
|
25
|
+
} catch {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Two strategies, in the same order the previous jq pipelines used:
|
|
32
|
+
* an exact context.cluster match first, then a cluster whose server URL contains the id.
|
|
33
|
+
* Returns the first match so a multi-context kubeconfig resolves the same way it did before.
|
|
34
|
+
*/
|
|
35
|
+
export const selectKubeContext = (
|
|
36
|
+
view: KubeConfigView | undefined,
|
|
37
|
+
clusterId: string,
|
|
38
|
+
): string | undefined => {
|
|
39
|
+
if (!view) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const contexts = view.contexts ?? [];
|
|
44
|
+
|
|
45
|
+
for (const entry of contexts) {
|
|
46
|
+
const name = asString(entry.name);
|
|
47
|
+
if (name !== undefined && asString(entry.context?.cluster) === clusterId) {
|
|
48
|
+
return name;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const clusters = view.clusters ?? [];
|
|
53
|
+
|
|
54
|
+
for (const entry of contexts) {
|
|
55
|
+
const name = asString(entry.name);
|
|
56
|
+
const clusterName = asString(entry.context?.cluster);
|
|
57
|
+
if (name === undefined || clusterName === undefined) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const matchesServer = clusters.some(
|
|
62
|
+
(cluster) =>
|
|
63
|
+
asString(cluster.name) === clusterName &&
|
|
64
|
+
(asString(cluster.cluster?.server) ?? "").includes(clusterId),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if (matchesServer) {
|
|
68
|
+
return name;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return undefined;
|
|
73
|
+
};
|
package/src/k8s-tool/service.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { posix } from "node:path";
|
|
2
2
|
|
|
3
3
|
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
|
|
4
|
-
import { Context, Effect, Layer, Option, Ref
|
|
4
|
+
import { Context, Effect, Layer, Option, Ref } from "effect";
|
|
5
5
|
|
|
6
6
|
import type { CommandResult, Environment } from "./types";
|
|
7
7
|
|
|
@@ -21,6 +21,7 @@ import { normalizeProfilePrerequisites } from "#shared/prerequisites/config";
|
|
|
21
21
|
import { runWithProfilePrerequisites } from "#shared/prerequisites/runtime";
|
|
22
22
|
import { buildApiProbeArgs } from "#shared/k8s-probe";
|
|
23
23
|
import { isKubectlCommandAllowed, isSafeLogPath } from "./security";
|
|
24
|
+
import { parseKubeConfigView, selectKubeContext } from "./context";
|
|
24
25
|
|
|
25
26
|
export class K8sService extends Context.Service<
|
|
26
27
|
K8sService,
|
|
@@ -98,41 +99,31 @@ export class K8sService extends Context.Service<
|
|
|
98
99
|
);
|
|
99
100
|
});
|
|
100
101
|
|
|
101
|
-
const withKubeconfig = (command: string, kubeconfig: string | undefined) =>
|
|
102
|
-
kubeconfig ? `KUBECONFIG=${quoteShellArg(kubeconfig)} ${command}` : command;
|
|
103
102
|
const renderArg = (arg: string) =>
|
|
104
103
|
/^[A-Za-z0-9_./:=,@+-]+$/.test(arg) ? arg : quoteShellArg(arg);
|
|
105
|
-
const renderKubectlCommand = (context: string, argv: readonly string[]) =>
|
|
106
|
-
["kubectl", "--context", context, ...argv].map(renderArg).join(" ");
|
|
104
|
+
const renderKubectlCommand = (context: string | undefined, argv: readonly string[]) =>
|
|
105
|
+
["kubectl", ...(context ? ["--context", context] : []), ...argv].map(renderArg).join(" ");
|
|
107
106
|
|
|
108
107
|
// Cache context by selected profile/cluster instead of a single default profile.
|
|
109
108
|
const contextRef = yield* Ref.make<Record<string, string>>({});
|
|
110
109
|
|
|
111
110
|
// Helper that uses executor.spawn() to avoid ChildProcessSpawner requirement in return type
|
|
112
|
-
const
|
|
111
|
+
const runKubectlCapture = (
|
|
112
|
+
argv: readonly string[],
|
|
113
|
+
kubeconfig: string | undefined,
|
|
114
|
+
timeoutMs: number,
|
|
115
|
+
renderedCommand: string,
|
|
116
|
+
) =>
|
|
113
117
|
Effect.scoped(
|
|
114
118
|
Effect.gen(function* () {
|
|
115
|
-
const command = ChildProcess.make("
|
|
119
|
+
const command = ChildProcess.make("kubectl", argv, {
|
|
116
120
|
stdout: "pipe",
|
|
117
121
|
stderr: "pipe",
|
|
122
|
+
...(kubeconfig ? { env: { KUBECONFIG: kubeconfig }, extendEnv: true } : {}),
|
|
118
123
|
});
|
|
119
124
|
const process = yield* executor.spawn(command);
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
Stream.decodeText(),
|
|
123
|
-
Stream.runCollect,
|
|
124
|
-
);
|
|
125
|
-
const stdout = stdoutChunk.join("");
|
|
126
|
-
|
|
127
|
-
const stderrChunk = yield* process.stderr.pipe(
|
|
128
|
-
Stream.decodeText(),
|
|
129
|
-
Stream.runCollect,
|
|
130
|
-
);
|
|
131
|
-
const stderr = stderrChunk.join("");
|
|
132
|
-
|
|
133
|
-
const exitCode = yield* process.exitCode;
|
|
134
|
-
|
|
135
|
-
return { stdout, stderr, exitCode };
|
|
126
|
+
return yield* collectProcessOutput(process);
|
|
136
127
|
}),
|
|
137
128
|
).pipe(
|
|
138
129
|
Effect.timeoutOption(timeoutMs),
|
|
@@ -140,7 +131,7 @@ export class K8sService extends Context.Service<
|
|
|
140
131
|
const missing = missingBinaryFromSpawnFailure("kubectl", String(platformError));
|
|
141
132
|
return new K8sCommandError({
|
|
142
133
|
message: `Command execution failed: ${String(platformError)}`,
|
|
143
|
-
command:
|
|
134
|
+
command: renderedCommand,
|
|
144
135
|
exitCode: -1,
|
|
145
136
|
stderr: String(platformError),
|
|
146
137
|
...(missing ? { hint: missing.hint } : {}),
|
|
@@ -214,56 +205,37 @@ export class K8sService extends Context.Service<
|
|
|
214
205
|
return { context: cachedContext, kubeconfig };
|
|
215
206
|
}
|
|
216
207
|
|
|
217
|
-
const
|
|
218
|
-
|
|
208
|
+
const viewCommand = renderKubectlCommand(undefined, ["config", "view", "-o", "json"]);
|
|
209
|
+
const viewResultOption = yield* runKubectlCapture(
|
|
210
|
+
["config", "view", "-o", "json"],
|
|
219
211
|
kubeconfig,
|
|
212
|
+
timeoutMs,
|
|
213
|
+
viewCommand,
|
|
220
214
|
);
|
|
221
215
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (Option.isNone(contextResultOption)) {
|
|
216
|
+
if (Option.isNone(viewResultOption)) {
|
|
225
217
|
return yield* new K8sTimeoutError({
|
|
226
218
|
message: `Context resolution timed out after ${timeoutMs}ms`,
|
|
227
|
-
command:
|
|
219
|
+
command: viewCommand,
|
|
228
220
|
timeoutMs,
|
|
229
221
|
});
|
|
230
222
|
}
|
|
231
223
|
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
if (contextResult.exitCode === 0 && contextResult.stdout.trim()) {
|
|
235
|
-
const resolvedContextValue = contextResult.stdout.trim();
|
|
236
|
-
yield* Ref.update(contextRef, (contexts) => ({
|
|
237
|
-
...contexts,
|
|
238
|
-
[cacheKey]: resolvedContextValue,
|
|
239
|
-
}));
|
|
240
|
-
return { context: resolvedContextValue, kubeconfig };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const fallbackCommand = withKubeconfig(
|
|
244
|
-
`kubectl config view -o json | jq -r '.contexts[] as $ctx | .clusters[] | select(.name == $ctx.context.cluster and (.cluster.server | contains("${k8sConfig.clusterId}"))) | $ctx.name' | head -1`,
|
|
245
|
-
kubeconfig,
|
|
246
|
-
);
|
|
224
|
+
const viewResult = viewResultOption.value;
|
|
247
225
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
command: fallbackCommand,
|
|
254
|
-
timeoutMs,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const fallbackResult = fallbackResultOption.value;
|
|
226
|
+
if (viewResult.exitCode === 0) {
|
|
227
|
+
const resolvedContextValue = selectKubeContext(
|
|
228
|
+
parseKubeConfigView(viewResult.stdout),
|
|
229
|
+
k8sConfig.clusterId,
|
|
230
|
+
);
|
|
259
231
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
232
|
+
if (resolvedContextValue !== undefined) {
|
|
233
|
+
yield* Ref.update(contextRef, (contexts) => ({
|
|
234
|
+
...contexts,
|
|
235
|
+
[cacheKey]: resolvedContextValue,
|
|
236
|
+
}));
|
|
237
|
+
return { context: resolvedContextValue, kubeconfig };
|
|
238
|
+
}
|
|
267
239
|
}
|
|
268
240
|
|
|
269
241
|
return yield* new K8sContextError({
|