feat: make hwlab v03 admin secret yaml driven
This commit is contained in:
@@ -120,6 +120,17 @@ export interface HwlabRuntimePublicExposureSpec {
|
||||
readonly apiProxy: HwlabRuntimePublicExposureFrpcProxySpec;
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeBootstrapAdminSpec {
|
||||
readonly username: string;
|
||||
readonly displayName: string;
|
||||
readonly passwordSourceRef: string;
|
||||
readonly passwordSourceKey: string;
|
||||
readonly passwordHashTransform: "hwlab-sha256";
|
||||
readonly secretName: string;
|
||||
readonly secretKey: string;
|
||||
readonly rolloutDeployment: string;
|
||||
}
|
||||
|
||||
export interface HwlabRuntimeLaneSpec {
|
||||
readonly lane: HwlabRuntimeLane;
|
||||
readonly nodeId: string;
|
||||
@@ -156,6 +167,7 @@ export interface HwlabRuntimeLaneSpec {
|
||||
readonly publicApiUrl: string;
|
||||
readonly stepEnv: Record<string, string>;
|
||||
readonly buildkit?: HwlabRuntimeBuildkitSpec;
|
||||
readonly bootstrapAdmin?: HwlabRuntimeBootstrapAdminSpec;
|
||||
readonly externalPostgres?: HwlabRuntimeExternalPostgresSpec;
|
||||
readonly publicExposure: HwlabRuntimePublicExposureSpec | null;
|
||||
readonly observability: HwlabRuntimeObservabilitySpec;
|
||||
@@ -196,6 +208,7 @@ interface HwlabLaneConfig {
|
||||
readonly public: { readonly webUrl: string; readonly apiUrl: string };
|
||||
readonly stepEnv: Record<string, string>;
|
||||
readonly buildkit?: HwlabRuntimeBuildkitSpec;
|
||||
readonly bootstrapAdmin?: HwlabRuntimeBootstrapAdminSpec;
|
||||
readonly externalPostgres?: HwlabRuntimeExternalPostgresSpec;
|
||||
readonly publicExposure: HwlabRuntimePublicExposureSpec | null;
|
||||
readonly observability: HwlabRuntimeObservabilitySpec;
|
||||
@@ -396,6 +409,7 @@ function laneConfig(id: HwlabRuntimeLane, raw: Record<string, unknown>): HwlabLa
|
||||
},
|
||||
stepEnv: optionalStringRecord(raw.stepEnv, `lanes.${id}.stepEnv`),
|
||||
buildkit: buildkitConfig(raw.buildkit, `lanes.${id}.buildkit`),
|
||||
bootstrapAdmin: bootstrapAdminConfig(raw.bootstrapAdmin, `lanes.${id}.bootstrapAdmin`),
|
||||
externalPostgres: externalPostgresConfig(raw.externalPostgres, `lanes.${id}.externalPostgres`),
|
||||
publicExposure: publicExposureConfig(raw.publicExposure, `lanes.${id}.publicExposure`),
|
||||
observability: observabilityConfig(raw.observability, `lanes.${id}.observability`),
|
||||
@@ -414,6 +428,7 @@ function laneTargetConfig(id: HwlabRuntimeLane, nodeId: string, baseRaw: Record<
|
||||
public: mergeOptionalRecord(baseRaw.public, targetRaw.public),
|
||||
stepEnv: mergeOptionalRecord(baseRaw.stepEnv, targetRaw.stepEnv) ?? {},
|
||||
buildkit: mergeOptionalRecord(baseRaw.buildkit, targetRaw.buildkit),
|
||||
bootstrapAdmin: mergeOptionalRecord(baseRaw.bootstrapAdmin, targetRaw.bootstrapAdmin),
|
||||
externalPostgres: mergeOptionalRecord(baseRaw.externalPostgres, targetRaw.externalPostgres),
|
||||
publicExposure: mergeOptionalRecord(baseRaw.publicExposure, targetRaw.publicExposure),
|
||||
observability: mergeOptionalRecord(baseRaw.observability, targetRaw.observability),
|
||||
@@ -430,6 +445,36 @@ function buildkitConfig(value: unknown, path: string): HwlabRuntimeBuildkitSpec
|
||||
};
|
||||
}
|
||||
|
||||
function sourceRefField(obj: Record<string, unknown>, key: string, path: string): string {
|
||||
const value = stringField(obj, key, path);
|
||||
if (!/^[A-Za-z0-9_./-]+$/u.test(value)) throw new Error(`${path}.${key} has an unsupported format`);
|
||||
return value;
|
||||
}
|
||||
|
||||
function secretKeyField(obj: Record<string, unknown>, key: string, path: string): string {
|
||||
const value = stringField(obj, key, path);
|
||||
if (!/^[A-Za-z0-9_.-]+$/u.test(value)) throw new Error(`${path}.${key} has an unsupported format`);
|
||||
return value;
|
||||
}
|
||||
|
||||
function bootstrapAdminConfig(value: unknown, path: string): HwlabRuntimeBootstrapAdminSpec | undefined {
|
||||
if (value === undefined) return undefined;
|
||||
const raw = asRecord(value, path);
|
||||
const transform = stringField(raw, "passwordHashTransform", path);
|
||||
if (transform !== "hwlab-sha256") throw new Error(`${path}.passwordHashTransform must be hwlab-sha256`);
|
||||
const rollout = asRecord(raw.rollout, `${path}.rollout`);
|
||||
return {
|
||||
username: stringField(raw, "username", path),
|
||||
displayName: stringField(raw, "displayName", path),
|
||||
passwordSourceRef: sourceRefField(raw, "passwordSourceRef", path),
|
||||
passwordSourceKey: secretKeyField(raw, "passwordSourceKey", path),
|
||||
passwordHashTransform: transform,
|
||||
secretName: stringField(raw, "secretName", path),
|
||||
secretKey: secretKeyField(raw, "secretKey", path),
|
||||
rolloutDeployment: stringField(rollout, "deployment", `${path}.rollout`),
|
||||
};
|
||||
}
|
||||
|
||||
function externalPostgresComponentConfig(value: unknown, path: string): HwlabRuntimeExternalPostgresComponentSpec {
|
||||
const raw = asRecord(value, path);
|
||||
return {
|
||||
@@ -603,6 +648,7 @@ function buildRuntimeLaneSpec(config: HwlabLaneConfig): HwlabRuntimeLaneSpec {
|
||||
publicApiUrl: config.public.apiUrl,
|
||||
stepEnv: config.stepEnv,
|
||||
...(config.buildkit === undefined ? {} : { buildkit: config.buildkit }),
|
||||
...(config.bootstrapAdmin === undefined ? {} : { bootstrapAdmin: config.bootstrapAdmin }),
|
||||
...(config.externalPostgres === undefined ? {} : { externalPostgres: config.externalPostgres }),
|
||||
publicExposure: config.publicExposure,
|
||||
observability: config.observability,
|
||||
|
||||
Reference in New Issue
Block a user