refactor: source codex sentinel names from yaml
This commit is contained in:
@@ -187,6 +187,8 @@ sentinel:
|
||||
credentialsSecretName: sub2api-account-sentinel-profiles
|
||||
stateConfigMapName: sub2api-account-sentinel-state
|
||||
cronJobName: sub2api-account-sentinel
|
||||
roleName: sub2api-account-sentinel
|
||||
roleBindingName: sub2api-account-sentinel
|
||||
model: gpt-5.5
|
||||
endpoint: responses
|
||||
marker:
|
||||
|
||||
@@ -14,6 +14,8 @@ export interface CodexPoolSentinelConfig {
|
||||
credentialsSecretName: string;
|
||||
stateConfigMapName: string;
|
||||
cronJobName: string;
|
||||
roleName: string;
|
||||
roleBindingName: string;
|
||||
model: string;
|
||||
endpoint: "responses";
|
||||
marker: {
|
||||
@@ -110,6 +112,8 @@ export function defaultCodexPoolSentinelConfig(): CodexPoolSentinelConfig {
|
||||
credentialsSecretName: "sub2api-account-sentinel-profiles",
|
||||
stateConfigMapName: "sub2api-account-sentinel-state",
|
||||
cronJobName: "sub2api-account-sentinel",
|
||||
roleName: "sub2api-account-sentinel",
|
||||
roleBindingName: "sub2api-account-sentinel",
|
||||
model: "gpt-5.5",
|
||||
endpoint: "responses",
|
||||
marker: {
|
||||
@@ -199,6 +203,8 @@ export function readCodexPoolSentinelConfig(value: unknown, defaults: CodexPoolS
|
||||
credentialsSecretName: readDnsName(valueAt(value, "credentialsSecretName"), `${sourcePath}.sentinel.credentialsSecretName`, defaults.credentialsSecretName),
|
||||
stateConfigMapName: readDnsName(valueAt(value, "stateConfigMapName"), `${sourcePath}.sentinel.stateConfigMapName`, defaults.stateConfigMapName),
|
||||
cronJobName: readDnsName(valueAt(value, "cronJobName"), `${sourcePath}.sentinel.cronJobName`, defaults.cronJobName),
|
||||
roleName: readRequiredDnsName(valueAt(value, "roleName"), `${sourcePath}.sentinel.roleName`),
|
||||
roleBindingName: readRequiredDnsName(valueAt(value, "roleBindingName"), `${sourcePath}.sentinel.roleBindingName`),
|
||||
model: readModelName(valueAt(value, "model"), `${sourcePath}.sentinel.model`, defaults.model),
|
||||
endpoint: "responses",
|
||||
marker: {
|
||||
@@ -276,6 +282,8 @@ export function codexPoolSentinelSummary(config: CodexPoolSentinelConfig): Recor
|
||||
actionsEnabled: config.actions.enabled,
|
||||
schedule: config.schedule,
|
||||
cronJobName: config.cronJobName,
|
||||
roleName: config.roleName,
|
||||
roleBindingName: config.roleBindingName,
|
||||
configMapName: config.configMapName,
|
||||
credentialsSecretName: config.credentialsSecretName,
|
||||
stateConfigMapName: config.stateConfigMapName,
|
||||
@@ -391,7 +399,7 @@ metadata:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: ${config.serviceAccountName}
|
||||
name: ${config.roleName}
|
||||
namespace: ${options.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${config.cronJobName}
|
||||
@@ -411,7 +419,7 @@ rules:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: ${config.serviceAccountName}
|
||||
name: ${config.roleBindingName}
|
||||
namespace: ${options.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${config.cronJobName}
|
||||
@@ -423,7 +431,7 @@ subjects:
|
||||
namespace: ${options.namespace}
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: ${config.serviceAccountName}
|
||||
name: ${config.roleName}
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
@@ -2097,6 +2105,15 @@ function readDnsName(value: unknown, key: string, fallback: string): string {
|
||||
return text;
|
||||
}
|
||||
|
||||
function readRequiredDnsName(value: unknown, key: string): string {
|
||||
if (value === undefined || value === null) throw new Error(`${key} is required`);
|
||||
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${key} must be a non-empty string`);
|
||||
if (/[\r\n]/u.test(value)) throw new Error(`${key} must not contain newlines`);
|
||||
const text = value.trim();
|
||||
if (!/^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/u.test(text)) throw new Error(`${key} must be a Kubernetes DNS label`);
|
||||
return text;
|
||||
}
|
||||
|
||||
function readModelName(value: unknown, key: string, fallback: string): string {
|
||||
const text = readString(value, key, fallback);
|
||||
if (!/^[A-Za-z0-9._:-]+$/u.test(text)) throw new Error(`${key} has an unsupported model name`);
|
||||
|
||||
@@ -1023,36 +1023,26 @@ function managedResourceCleanupPlan(sub2api: Sub2ApiConfig, target: Sub2ApiTarge
|
||||
}
|
||||
|
||||
function codexPoolSentinelResourceNames(): ManagedResourceCleanupPlan["sentinel"] {
|
||||
const defaults: ManagedResourceCleanupPlan["sentinel"] = {
|
||||
enabled: false,
|
||||
cronJobName: "sub2api-account-sentinel",
|
||||
configMapName: "sub2api-account-sentinel-config",
|
||||
credentialsSecretName: "sub2api-account-sentinel-profiles",
|
||||
stateConfigMapName: "sub2api-account-sentinel-state",
|
||||
serviceAccountName: "sub2api-account-sentinel",
|
||||
roleName: "sub2api-account-sentinel",
|
||||
roleBindingName: "sub2api-account-sentinel",
|
||||
};
|
||||
if (!existsSync(codexPoolConfigPath)) return defaults;
|
||||
if (!existsSync(codexPoolConfigPath)) throw new Error(`${codexPoolConfigPath} is required for Sub2API codex-pool sentinel cleanup resource names`);
|
||||
const parsed = Bun.YAML.parse(readFileSync(codexPoolConfigPath, "utf8")) as unknown;
|
||||
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return defaults;
|
||||
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error(`${codexPoolConfigPath} must be an object`);
|
||||
const sentinel = (parsed as Record<string, unknown>).sentinel;
|
||||
if (typeof sentinel !== "object" || sentinel === null || Array.isArray(sentinel)) return defaults;
|
||||
if (typeof sentinel !== "object" || sentinel === null || Array.isArray(sentinel)) throw new Error(`${codexPoolConfigPath}.sentinel must be an object`);
|
||||
const record = sentinel as Record<string, unknown>;
|
||||
const text = (key: string, fallback: string): string => {
|
||||
const value = record[key];
|
||||
return typeof value === "string" && value.length > 0 ? value : fallback;
|
||||
const resourceName = (key: string): string => {
|
||||
const value = stringField(record, key, "sentinel");
|
||||
validateKubernetesResourceName(value, `sentinel.${key}`);
|
||||
return value;
|
||||
};
|
||||
const serviceAccountName = text("serviceAccountName", defaults.serviceAccountName);
|
||||
return {
|
||||
enabled: false,
|
||||
cronJobName: text("cronJobName", defaults.cronJobName),
|
||||
configMapName: text("configMapName", defaults.configMapName),
|
||||
credentialsSecretName: text("credentialsSecretName", defaults.credentialsSecretName),
|
||||
stateConfigMapName: text("stateConfigMapName", defaults.stateConfigMapName),
|
||||
serviceAccountName,
|
||||
roleName: serviceAccountName,
|
||||
roleBindingName: serviceAccountName,
|
||||
cronJobName: resourceName("cronJobName"),
|
||||
configMapName: resourceName("configMapName"),
|
||||
credentialsSecretName: resourceName("credentialsSecretName"),
|
||||
stateConfigMapName: resourceName("stateConfigMapName"),
|
||||
serviceAccountName: resourceName("serviceAccountName"),
|
||||
roleName: resourceName("roleName"),
|
||||
roleBindingName: resourceName("roleBindingName"),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user