调理工具箱
客户端、 客户端提供者、 数据源、 环境连接和客户端管理器为兄弟端类型Script包所有
@compforge/harness-common. 工具箱提供协议执行和运输;
它的生命周期入境点再出口相同的共同符号.
共享诊断工具、试验跑道和商业适配器的基础设施。 用同样的 客户端访问 HTTP( S), Kubernetes, MySQL, Redis, OpenSearch 和 S3 兼容对象存储而不取决于特定对象 命令、插件协议、测试模型或判断.
该软件包支持Node.js 22+和 Bun. 安装方式 npm install @compforge/harness-toolbox。 。 。 .
使用 @compforge/harness-toolbox/duration 以分析正时长, 如 30m 或者说 2d 变成毫秒.
searchAfterPages 从 @compforge/harness-toolbox/opensearch/search-after 生成原始 OpenSearch
提供查询和稳定排序。 它在不拥有客户端的情况下流出页面或
声称快照一致性; 呼叫者提供取消,并决定如何坚持或核实结果.
协议适配器设有单独的切入点;进口生命周期或运输合同确实如此
不装入数据库或 Kubernetes 驱动程序.
HTTP 请求
HttpClient 借同样的 Transport 作为其他协议客户端,保留逻辑主机和
TLS 身份, 即使套接字通过端口前行 。 限制包括反应机构;
状态和重定向在返回时不重复或重定向.
import { ClientManager } from "@compforge/harness-common";
import { HttpClient } from "@compforge/harness-toolbox/http";
import { DirectTransport } from "@compforge/harness-toolbox/transport";
const clients = new ClientManager();
try {
const route = await clients.get({ clientKey: "direct", createClient: () => new DirectTransport() });
const http = await clients.create({ createClient: (_clients, signal) => new HttpClient(
{ endpoint: "https://service.example" }, route,
{ concurrency: 4, connectTimeoutMs: 5000, requestTimeoutMs: 10000, maxResponseBytes: 1024 * 1024 },
{ signal },
) });
const response = await http.request("/health");
console.log(response.status, new TextDecoder().decode(response.body));
await http.dispose(); // The shared route remains available until root disposal.
} finally { await clients.dispose(); }
文件来源
一个FileData Source是一个呼叫者宣布的收购集团. 使用 LocalFileDataSource 本地路径
或者说 PodFileDataSource 用于一个明确名称空间/Pod/容器中的路径。 两个扩展的普通
FileDataSource;不需要额外的id/kind包装.
import { ClientManager } from "@compforge/harness-common";
import { LocalFileDataSource, PodFileDataSource } from "@compforge/harness-toolbox/file";
const source = new LocalFileDataSource(["./config.yaml", "./secret/config.yaml"], { concurrency: 2 });
const clients = new ClientManager();
try {
const file = await clients.get(source);
const results = await file.read({ maxBytes: 1024 * 1024, maxTotalBytes: 2 * 1024 * 1024, timeoutMs: 15_000 });
for (const result of results) {
if (result.status === "error") console.error(result.path, result.error.message);
else console.log(result.path, new TextDecoder("utf-8", { fatal: true }).decode(result.bytes));
}
} finally { await clients.dispose(); }
// Resolve Workloads first. This entire group is fetched through one exec session.
const podSource = new PodFileDataSource(environment,
{ namespace: "app", pod: "worker-abc", container: "worker" },
["/etc/app/config.yaml", "/etc/app/secret/config.yaml"], { concurrency: 2 });
每个读取重开所有已声明的路径并返回每个路径一个命令的结果 。 空文件成功; 缺少、否定、非常规和超大小的文件返回单个错误,没有部分字节. 一个文件中的错误不会丢弃兄弟间的结果 。 每一路径的每个文件限制重设; 总计 预算约束保留了解码字节,包括不完整的文件. 排队和整组 共享一个最后期限。 取消、总预算用完、最后期限和运输/议定书失效 拒绝手术 源代码共享客户端, 从没有之前的文件内容 .
Pod 组使用一个执行器并需要 sh, (中文(简体) ), head -c, (中文(简体) ), base64 财务报告和审定财务报表 tr。 路径仍然定位
参数,即使包含 shell 语法或新行。 已索引的 Base64 记录带有原始二进制
字节加每个文件的退出状态;不重放便被截断或错误的记录拒绝. 无远程
临时文件被写入 。 本地读取允许将符号链接到正则文件并拒绝非正则文件.
将路径和Pod目标保持在证据上; 分组保证既不保证原子文件系统快照
或应用程序配置优先。 Pod 名称不是 UID 栅栏; 需要化身的呼叫者
保证必须检查收集周围的发现。 文件客户端借用 root Kubernetes 访问和
永远不要关闭它自己.
0.4.2版本要求通用0.5.4. 将单一路径参数替换为数组, 供应 maxTotalBytes, (中文(简体) ),
并处理每个文件的结果。 在 Toolbox 之前发布 Common; 此更改没有单文件的遗留适配器 .
Redis 来源
RedisClient 拥有已解析的配置和可再使用的节点连接。 使用 clusterType 改为
选择 single, (中文(简体) ), cluster 或者说 sentinel· ; endpoints 包含该模式的种子地址。 哨兵队
配置额外提供 sentinelMasterName 和可选的哨兵证书,
与数据节点证书分开。 集群连接需要数据库零.
供应一 Transport,在需要的地方有命令的 TCP 路径。 只有映射或握手网络
失败推进到下个传输;认证和TLS验证失败立即停止.
connectTimeoutMs 绑定每个路由( 映射和握手); 它默认为命令
timeoutMs。 。 。 . acquireTimeoutMs 将所有候选人合并在一起,并缺省到每个路线的预算
乘以路线数。 已经花费的总预算不会开始另一条路线.
onRoute 报告选中的路由和之前的失败代码,没有证书.
client.topology() 使用与
client.access.connection(endpoint, database)。根信号取消连接准备
活动命令。 命令和管道发送一次,没有下线排队或自动回放;
之后的购买取代了不健康的连接。 打电话者拥有 dispose() 运输
清理,诊断者拥有取样政策和收集观测结果.
库伯涅斯资源
借用根 KubernetesClient 结束 KubernetesEnvironment 财务报告和审定财务报表 ClientManager启用
get(ref) 财务报告和审定财务报表 list(query) 资源读取; inNamespace(namespace) 绑定所借视图
不创建第二个客户端或集合的命名空间 :
const kube = await clients.get(environment);
const ns = kube.inNamespace("app");
const service = await ns.get({ apiVersion: "v1", resource: "services", name: "api" });
const pods = await ns.list({ apiVersion: "v1", resource: "pods", labelSelector: "app=api" },
{ timeoutMs: 15_000, signal });
resource 是复数 REST 资源名称,而不是 Kind 或 kubectl 化名。 明确的 API 版本
支持内置资源和自定义资源,无需发现请求或本地许可列表.
根使用它所配置的命名空间, 除非查询超过它; 命名空间视图强制
他们的边框命名空间。 资源对象和列表元数据完整地返回. 名单请求
接受标签/字段选择并明确 limit编号 :continue 页面;它们不默读所有页面.
错误是 KubernetesError 带有稳定类型和HTTP状态的物体.
呼叫者以其证据保留了查询;资源操作不会产生 shell 命令结果.
Root 拥有一个 HTTP 传输, 拥有在命名空间和资源之间共享的恒活连接
类型。 每次请求都会刷新认证 。 TLS/ 代理身份更改 选择新池并
上一个在读完后退休。 请求有字节和最后期限
包括队列、认证和身体消耗. dispose() 取消工作, 等待跟踪
操作,并关闭连接。 视图和注入所借资源阅读器没有所有权
这生命周期。 没有查询结果被缓存,失败永远不会通过另一个传输重放.
本地资源访问使用 kubeconfig 认证、 TLS 和 明文 proxy-url它不会
基于 shell 代理环境变量选择传输. exec 财务报告和审定财务报表 forward 分开
流式操作;其执行不截取读取资源. KubernetesClient
没有 run(argv) 方法。 货币仍由调用人组成,而不是从池大小推断.
工作量的发现
通过 Kubernetes Environment 和 共享客户端管理器生命周期借取 Kubernetes 客户端
client.resolveWorkload(workload, environmentId)。ID是一个稳定的目标身份 从您
环境注册,而不是显示名称或 kubeconfig 路径。 Workload的命名空间可以覆盖客户端的默认值.
资源、 服务选择器和标签位置返回所有匹配的 Pod 化身而不包含
准备过滤; 成功的空发现返回空阵列。 缺少资源,
无选择服务, 访问失败 .
资源路径使用客户端-node kubeconfig认证/TLS,并被捆绑的本地JSON读取:, 不是 kubectl 错误文本 。 使用 客户端的资源Limits构建器参数。 Exec 使用相同的根能/字节政策 拥有一个单独的槽池;其每次呼叫的超时都会默认该策略并覆盖排队, 认证、升级和执行。 明确的呼叫暂停支持更长的命令.
只输出的Exec直接连接到波德Exec WebSocket的端点而无需初步
Pod 获取和需要 get pods/exec。带有明确 stdin(包括空输入)使用的命令
kubectl exec -i,它通过 SPDY/v5 处理关于更古老和更新的集群的输入 EOF。 这个
路径需要 Host 上兼容的 kubectl, Pod 读取权限和 create pods/exec
sPDY (英语:get pods/exec 用于 WebSocket 。 执行前选择频道; 失败
从未被工具箱重试或重放。 结果 command 记录实际频道.
Kubeconfig控制认证,TLS和代理访问. 两个路径共享根执行槽
池、 截止日期、 保留输出字节限制和取消 。 stdout/stder 仍然分开;
本地 exec 使用远程状态, kubectl 使用进程退出状态, 保留原始 CLI stderr
不猜测结构化的 HTTP 错误类型 。 串流呼叫器可能设置 collectStdout: false
并且执行自己的总字节预算; 单个产出块仍然有限制。 根处理
取消活动会话和队列会话,等待本地的kubectl进程退出.
只输出会话接受v4/v5. Bun没有显示 HTTP 升级拒绝状态,所以
失败保留了未知的连接错误 。 有 kubeconfig 代理的本地执行需要节点 :
Bun 无法可靠地释放代理套接字或保存 TLS 名称覆盖 。 这个限制是
不适用于 kubectl stdin 路径 。 路径都无法绕过代理或 TLS 检查 .
前港也使用克贝克特克.
见 共享工作量模型。 。 。 .
import { ClientManager, EnvironmentContext } from "@compforge/harness-toolbox";
import { KubernetesEnvironment } from "@compforge/harness-toolbox/kubernetes/environment";
const clients = new ClientManager();
try {
const ctx = new EnvironmentContext(
new KubernetesEnvironment("dev",
{ kubeconfig: "/config/cluster", context: "dev", namespace: "app" },
{ timeoutMs: 10_000, concurrency: 4, maxBytes: 8 * 1024 * 1024 }),
clients, performance.now() + 30_000,
);
const kube = await ctx.clients.get(ctx.environment);
const pods = await kube.resolveWorkload({
name: "api", platform: "kubernetes",
location: { kind: "resource", resource_kind: "Deployment", name: "api" },
}, "cluster-a/runtime");
} finally {
await clients.dispose();
}
上下文不会自动取消工作 。 其预算尚存。 老师; root拥有注销权,在处置客户前必须加入童工.
从根项抓取工具框错误或 @compforge/harness-toolbox/errors; 使用 kind 财务报告和审定财务报表
code 用于决定。 土著 cause 可能包含敏感细节,并且只调试.
连接获取截止日期和 Redis 握手/ 命令截止日期 TimeoutError
从 @compforge/harness-toolbox/errors它延伸 ToolboxError,保留
kind: "timeout" 财务报告和审定财务报表 code: "ETIMEDOUT"; OpenSearch 保存不变.
为协调的通用/工具箱开发,在安装工具箱前安装和构建通用工具箱:
# From sdks/typescript/toolbox
(cd ../common && bun install --frozen-lockfile && make build)
bun install --frozen-lockfile
make lint
make test
工具箱根覆盖从 ../common 仅供地方发展之用;
已公布的依赖关系仍然是登记版本。 在工具箱前公布常见信息 .
Makefile 在排入或构建工具箱之前建立常见文件 .
A 类 ClientProvider 识别可重复使用的客户端并构建它; DataSource 添加数据访问语义.
无障碍环境在不成为数据源的情况下直接执行客户端提供. 这个 Client 拥有初始化
(a) 处置 ClientManager 加入同一密钥同时初始化,并
呼叫者完成后关闭自有客户端 。 协议客户端接受配置( 或自动解析器)
和一个 Transport; 运输选择和准备访问路径. clients.create(factory) 创建
其打电话者可能提前关闭的新客户端 get 留活口,直到根处理.
共享端口,登记 a ServicePortForwardTransport 每组/名称空间一次,然后通过
借给每个协议客户端的运输。 关闭 OpenSearch 客户端将可用的前端留给下一个
OpenSearch, MySQL, Redis 或 S3 客户端; root 处理在停止前关闭客户端.
借款人的取消只停止了借款人的等待。 退出前置在下一次获取时重新创建 .
运算映射改变拨号地址,而协议客户端保留了原始主机,TLS和签名身份.
在0.5中,替换 new Client({ resolve, transports }, options) 与
new Client(resolve, transport, options) (S3保留其明确的限制理由).
import { ClientManager, clientKey, type DataSource } from "@compforge/harness-toolbox";
import { MysqlClient } from "@compforge/harness-toolbox/mysql";
import { DirectTransport } from "@compforge/harness-toolbox/transport";
const target = { host: "localhost", port: 3306, database: "app", user: "reader", password: "..." };
const source: DataSource<MysqlClient> = {
clientKey: clientKey("mysql", target),
createClient: (_clients, signal) => new MysqlClient(target, new DirectTransport(),
{ signal, connectTimeoutMs: 5_000, queryTimeoutMs: 10_000 }),
};
const clients = new ClientManager();
try {
const db = await clients.get(source);
const rows = await db.database.query(db.target, "SELECT 1 AS value", []);
} finally {
await clients.dispose();
}
呼叫者拥有证书,授权,查询语义,容量和超时. MySQL 可以使用 TCP或Python-capable Pod;后者需要PyMySQL. 运输回落只发生在 建立连接,绝不通过重放失败的 SQL 操作。 Pod 输入使用 stdin .
Pod 日志抓取共享一个相同的 Pod/ 容器实例和一次绝对时间窗口 客户端,而消费者独立过滤并保留自己的原始副本。 提供明确的 抓取策略、 共享货币池和字节预算; 软件包不选择产品 限制。 临时抓取文件直播直到客户端处理.
见 工具箱合同 为所有权和跨语言语义.
读取 S3 对象
S3使用官方的AWS SDK在同一个被管理的生命周期后. 供应解决连接 设置和明确的限制; 软件包没有发现业务配置或证书.
import { ClientManager } from "@compforge/harness-toolbox";
import { S3DataSource } from "@compforge/harness-toolbox/s3";
const clients = new ClientManager();
try {
const s3 = await clients.get(new S3DataSource({
endpoint: "https://s3.example.com", region: "us-east-1",
credentials: { accessKeyId: "...", secretAccessKey: "..." },
}, { concurrency: 4, connectTimeoutMs: 5_000, requestTimeoutMs: 15_000 }));
const object = await s3.headObject("artifacts", "runs/example.json");
const prefix = await s3.readObject("artifacts", "runs/example.json", { maxBytes: 65_536 });
// prefix.truncated distinguishes a bounded prefix from the complete object.
} finally {
await clients.dispose();
}
listObjects 财务报告和审定财务报表 listBuckets 返回带有继续符号的有明确界限的页面;
呼叫者拥有整个扫描预算 Bucket Head和版本也可用.
错误保存 SDK 状态/ 代码: 失败的头部没有转换为 exists=false。阅读停止于
字节盖并关闭正文; 请求截止日期包括排队和体能消耗.
没有写入操作,自动重试或隐含的区域重定向被曝光.
对于绘制的TCP运输,通过 { key: "cluster/context identity", transport } 作为第三个
数据来源论证. 来电者拥有运输的一生. 需要路径式地址
用于绘制路径; 直接端点也支持虚拟托管桶。 已签名的主机和 TLS
身份仍然是逻辑终点,而不是转发地址。 可提供私人CA
明确使用 ca; 证书验证仍然启用。 初始化准备客户端
和路线,不列出桶或声称证书已经验证.
边界 MySQL 读取
MysqlClient.database.queryReadonly(target, sql, values, { timeoutMs, maxRows, maxBytes }) 用途
共享查询位置和可支配本地会话 NO_BACKSLASH_ESCAPES一个SELECT的最后期限,
和只读交易。 准备执行会绑定值并逐步保留行,
返回时 rows, (中文(简体) ), columns, (中文(简体) ), bytes, (中文(简体) ), truncated,以及 truncation。额外一行证明行切换;
a 不保留超过所余字节预算的行.
呼叫者拥有 SQL 分类、功能政策和最低特权身份:只读 EAD
不是任意的 SQL 沙盒。 这个API需要 MySQL 5.7.8+ max_execution_time 没有
倒倒倒波德活佛. 完成、缩短、超时和取消销毁一次性
会话没有重放或更改普通借用会话。 断接不能证明是即时的
服务器取消。 字节预算限制保留了JSON行,而不是单个线包或字段.
可重用绑定的查询并读取缓存
对于可信,呼叫者拥有的SELECT声明, queryLimited(database, target, statement, maxRows)
附加整数 LIMIT maxRows + 1 返回时 { rows, truncated }. SQL 绝不能已经拥有
LIMIT或后继终止;帮助者不解析或重写任意的 SQL. 商业价值
保留约束参数. limitedStatement 财务报告和审定财务报表 limitedRows 披露相同的准备/预测
页:1 Database.queryBatch。 。 。 . maxRows 必须是低于2147483647的正整数。 这些帮手
只绑定行数:使用 queryReadonly 当一次性只读会话和字节/时间预算
需要这样做.
DataLoader 在一个明确解读的范围内分享结果、失败和飞行中的工作,类似于
瓜娃的"加载卡切"但范围为一发一发. 消费者不得改变共同的成果.
使用 withReadScope (b) 不使用它写作或投票.
import { DataLoader } from '@compforge/harness-toolbox/data-loader';
import { withReadScope, queryLimited } from '@compforge/harness-toolbox/mysql';
const scope = new DataLoader({
maxEntries: 256, maxBytes: 4 * 1024 * 1024, signal: client.signal,
});
const reads = withReadScope(client.database, scope);
try {
const page = await queryLimited(reads, client.target, {
sql: 'SELECT id FROM items WHERE owner = ? ORDER BY id', values: [owner],
}, 100);
} finally {
await scope.close(); // Root still owns client.dispose().
}
密钥包括完整的数据库身份,SQL和打入的参数作为不透明摘要. 不连续 参数绕行缓存。 批次读取再利用缓存条目并按本地命令发送错失 批号,或无法批号时的顺序查询。 失败不重放而共享; 使用新的观测范围。 这不是一个一致的数据库快照.
入站容量包括失败和待读;新密钥在满时会绕行缓存. 序列化
结果字节绑定保留结果,不包括密钥/errors和活操作内存. 超规模
或非顺序结果返回但不保留。 范围 关闭信号取消并加入
操作,包括未标记的读取。 行动必须尊重迅速取消的信号;
MySQL读取保留其基本的客户端超时/取消政策. 适配器关闭时也不拥有
范围或数据库。 服务员的可选信号 scope.read 只取消那个服务员.
共享 Pod中继运输
PodRelayTransport 通过现有的 Running/Ready Pod 打开 TCP 路由。 它发现一个
选定命名空间中符合条件的容器(可选择由标签选择器限制)
当前执行使用 Python 3.8+ 标准图书馆 Ayncio. 呼叫者提供终点,
不是一个Pod名或口译员。 它不创建 Pods 并安装任何软件包 。 选中的 Pod
必须能够解决并到达每个目的地.
在 root 执行的客户端管理器中创建一个传送器, 并将其借给 Service/ protocol 客户。 它的密钥描述了集群访问和中继政策,从来不是服务或数据库身份. 同时代的呼叫者共享Pod发现,每个主机/端口一个接力过程和一个前置过程. 数据库 证书和连接仍然归其协议客户所有.
import { ClientManager } from '@compforge/harness-toolbox';
import { PodRelayTransport } from '@compforge/harness-toolbox/transport';
const clients = new ClientManager();
try {
const relay = await clients.get({
clientKey: 'transport:customer-cluster:app',
createClient: (_clients, signal) => new PodRelayTransport({
kubeconfig: '/config/cluster', context: 'customer', namespace: 'app',
selector: 'diagnostic-relay=eligible',
startupTimeoutMs: 5000, connectTimeoutMs: 5000,
maxConnections: 16, maxTargets: 8, maxCandidatePods: 8, signal,
}),
});
// Pass this same transport instance to each protocol client; clients never dispose it.
const address = await relay.connect({host: 'database.internal', port: 3306});
// Connect the native protocol client to address; do not dispose relay in a Service.
} finally {
await clients.dispose();
}
主办方必须授权 list pods, (中文(简体) ), create pods/exec 财务报告和审定财务报表 create pods/portforward,包括:
在选定的容器中运行一个临时进程。 清单/发现和每次准备行动
使用启动TimeoutMs; 候选的Pod计数、目标计数和集合的活继电器连接为
分别相接. 列表 socks 是命名空间范围 。 中继收听器只绑入波德回路和
本地转发仅用于主机回回转 。 控制信件包含目的地, 绝不是 DB 证书 .
处理关闭前置和执行流; EOF关闭远程收听器/连接. 如果执行官 无 EOF 连接已丢失, 一个30秒的心跳租赁会限制远程进程寿命 . 死继电器会使其路由无效并失效的呼叫者;没有重放SQL或其他协议操作. 根应在处置运输之前完成或取消协议工作.
OpenSearch 连接准备
openOpenSearch 在返回前对已解决的终点进行探测。 它尝试了提供的TCP运输
仅用于连接失败; HTTP 授权/服务器出错停止准备, 而失败
读取不再在其它路线上重放. onRoute 报告选定的运输和安全后退
理由,你觉得呢? 呼叫者拥有共享的运输工具,例如 PodRelayTransport 和他们的清理.
Routed HTTPS保留了原来的TLS服务器名. Bun 禁用 HTTP 保留活性,因为它被再利用 套接字恢复可在驱动程序下方重放失败的请求; 节点保留连接集合 .
计算证据
kubernetes/compute 出口 collectClusterCompute 财务报告和审定财务报表 collectWorkloadCompute他们借钱
获取资源,使用明确的截止日期/项目/页数预算,并独立保留阅读范围.
使用 client.clusterResources() 用于节点和全名空间 Pods; 普通客户端方法保留其
已配置命名空间 。 禁用集群读取记录 permission_denied; 它不阻断一个
单独命名空间范围的工作负荷读取。 见 计算收藏。 。 。 .
连接获取截止日期
MySQL,OpenSearch和Redis使用相同的收购生命周期. connectTimeoutMs 包括路线绘图
和握手/检测;可选 acquireTimeoutMs 将所有路由绑定在一起( 默认: 每个路由预算 × 路由计数) .
取消会保留呼叫者的理由并阻止后期映射开始握手. 查询和命令
超时仍然单独进行,失败的操作从不在另一运输上重放.
数据记录器接受可选选项 logger.debug(message) 和不敏感 label。 。 。 .
诊断方法区分误差、等值、被击中、绕行、不保留和使用范围/读取的相近
标识符,从不按键,数值或出错。 记录不会改变保留或重试政策.
网络连接
@compforge/harness-toolbox/network 出口 probeConnectivity(endpoint, execute, {timeoutMs, signal?})。 。 。 .
它会消耗 Endpoint 从 @compforge/harness-common· ; ConnectivityTarget 删除.
import type { Endpoint } from "@compforge/harness-common";
import { endpointFromUrl, validateEndpoint } from "@compforge/harness-toolbox/endpoint";
const endpoint: Endpoint = endpointFromUrl("https://storage.example:9443/object?signature=private");
// { scheme: "https", host: "storage.example", port: 9443, secure: true }
validateEndpoint(endpoint); // Pure validation; no DNS or I/O.
URL投影会降低资质,路径,查询和片段,并解压IPv6主机.
HTTP(S),WS(S)和FTP都有默认的端口. 这个 tls 方案需要端口和设置 secure: true。 。 。 .
其他计划需要明确的港口和出港条件
secure 未说明; 调用者从协议配置中提供任何加密要求 .
出错不会暴露原始的 URL 。 将完整的 URL 单独保存用于资源访问 .
secure 替换 tls 在探测输入和结果目标。 HTTPS/WSS/TLS要求 secure: true· ;
HTTP/WS拒绝. 与 secure: true,该探测器支持直接 TLS 用于 https, (中文(简体) ), wss,以及
明确 tls 计划。 其他计划或缺失的计划 ProtocolError 联合国 ToolboxError 与 kind: "protocol", (中文(简体) ), code: "Unsupported"(中文(简体) )
执行前: 协议谈判的加密, 如 MySQL 或 SSTATLS 未执行 .
没有加密要求,成功的TCP检查不能证明应用程序-protocol
可用性或加密。 TLS仍然是被观测到的握手阶段的名称.
呼叫者在消费环境(主机、Pod或沙盒)提供执行器,
运行 Python 3 与 供给的 argv 和 stdin 并强制超时/取消.
DNS,TCP和可选验证的TLS有分别的结果和时间. 域名,( 域名),
IP 字元和库伯内特 service.namespace 名称使用相同的API。 没有
在呼叫器主机或ICMP要求上隐含执行. 网络失败返回
; 缺少 Python 、 执行失败和不完全输出抛出 。 TLS 成功
不建立 HTTP 授权、 对象访问或应用程序下载政策.