Files
autoglue/ui/src/api/clusters.ts
Irfan Paraniya 385affb1d7 feat: Implement cluster metadata key-value store (Closes #302) (#834)
* feat: add cluster metadata key-value store

- Add ClusterMetadata model with ClusterID FK, key, value fields
- Add Metadata []ClusterMetadata relation to Cluster model
- Add CRUD handlers: List, Get, Create, Update, Delete cluster metadata
  - Keys are forced to lowercase on create/update
  - Values preserve case sensitivity
- Add metadata routes under /clusters/{clusterID}/metadata
- Include metadata in ClusterResponse DTO and clusterToDTO mapping
- Add Preload(Metadata) to all cluster queries
- Register ClusterMetadata in AutoMigrate

Closes: internal-GlueOps/issues#302

* feat: include cluster metadata in prepare payload

- Preload cluster Metadata in ClusterPrepareWorker
- Map cluster metadata into mapper.ClusterToDTO response payload

This ensures metadata key-value pairs are injected into the platform JSON payload used by prepare/bootstrap flows.

* feat: add cluster metadata UI section to configure dialog

* feat: simplify cluster metadata to map[string]string in response

* fix: address cluster metadata PR review feedback

Agent-Logs-Url: https://github.com/GlueOps/autoglue/sessions/f767d4b8-ecae-4cde-bb5c-f0845c5a7cdf

Co-authored-by: yesterdaysrebel <256862558+yesterdaysrebel@users.noreply.github.com>

* chore: finalize review feedback updates

Agent-Logs-Url: https://github.com/GlueOps/autoglue/sessions/f767d4b8-ecae-4cde-bb5c-f0845c5a7cdf

Co-authored-by: yesterdaysrebel <256862558+yesterdaysrebel@users.noreply.github.com>

* chore: revert unintended go.sum change

Agent-Logs-Url: https://github.com/GlueOps/autoglue/sessions/f767d4b8-ecae-4cde-bb5c-f0845c5a7cdf

Co-authored-by: yesterdaysrebel <256862558+yesterdaysrebel@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: yesterdaysrebel <256862558+yesterdaysrebel@users.noreply.github.com>
2026-04-17 11:05:49 +05:30

175 lines
5.0 KiB
TypeScript

import { withRefresh } from "@/api/with-refresh";
import type { DtoAttachBastionRequest, DtoAttachCaptainDomainRequest, DtoAttachLoadBalancerRequest, DtoAttachRecordSetRequest, DtoCreateClusterRequest, DtoSetKubeconfigRequest, DtoUpdateClusterRequest } from "@/sdk";
import { makeClusterApi, makeClusterMetadataApi, makeClusterRunsApi } from "@/sdkClient";
const clusters = makeClusterApi()
const clusterRuns = makeClusterRunsApi()
const clusterMetadata = makeClusterMetadataApi()
export const clustersApi = {
// --- basic CRUD ---
listClusters: (q?: string) =>
withRefresh(async () => {
return await clusters.listClusters(q ? { q } : {})
}),
getCluster: (id: string) =>
withRefresh(async () => {
return await clusters.getCluster({ clusterID: id })
}),
createCluster: (body: DtoCreateClusterRequest) =>
withRefresh(async () => {
return await clusters.createCluster({
createClusterRequest: body,
})
}),
updateCluster: (id: string, body: DtoUpdateClusterRequest) =>
withRefresh(async () => {
return await clusters.updateCluster({
clusterID: id,
updateClusterRequest: body,
})
}),
deleteCluster: (id: string) =>
withRefresh(async () => {
return await clusters.deleteCluster({ clusterID: id })
}),
// --- kubeconfig ---
setKubeconfig: (clusterID: string, body: DtoSetKubeconfigRequest) =>
withRefresh(async () => {
return await clusters.setClusterKubeconfig({
clusterID,
setClusterKubeconfigRequest: body,
})
}),
clearKubeconfig: (clusterID: string) =>
withRefresh(async () => {
return await clusters.clearClusterKubeconfig({ clusterID })
}),
// --- captain domain ---
attachCaptainDomain: (clusterID: string, body: DtoAttachCaptainDomainRequest) =>
withRefresh(async () => {
return await clusters.attachCaptainDomain({
clusterID,
attachCaptainDomainRequest: body,
})
}),
detachCaptainDomain: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachCaptainDomain({ clusterID })
}),
// --- control plane record set ---
attachControlPlaneRecordSet: (clusterID: string, body: DtoAttachRecordSetRequest) =>
withRefresh(async () => {
return await clusters.attachControlPlaneRecordSet({
clusterID,
attachControlPlaneRecordSetRequest: body,
})
}),
detachControlPlaneRecordSet: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachControlPlaneRecordSet({ clusterID })
}),
// --- load balancers ---
attachAppsLoadBalancer: (clusterID: string, body: DtoAttachLoadBalancerRequest) =>
withRefresh(async () => {
return await clusters.attachAppsLoadBalancer({
clusterID,
attachAppsLoadBalancerRequest: body,
})
}),
detachAppsLoadBalancer: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachAppsLoadBalancer({ clusterID })
}),
attachGlueOpsLoadBalancer: (clusterID: string, body: DtoAttachLoadBalancerRequest) =>
withRefresh(async () => {
return await clusters.attachGlueOpsLoadBalancer({
clusterID,
attachAppsLoadBalancerRequest: body,
})
}),
detachGlueOpsLoadBalancer: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachGlueOpsLoadBalancer({ clusterID })
}),
// --- bastion ---
attachBastion: (clusterID: string, body: DtoAttachBastionRequest) =>
withRefresh(async () => {
return await clusters.attachBastionServer({
clusterID,
attachBastionServerRequest: body,
})
}),
detachBastion: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachBastionServer({ clusterID })
}),
// -- node-pools
attachNodePool: (clusterID: string, nodePoolID: string) =>
withRefresh(async () => {
return await clusters.attachNodePool({
clusterID,
attachNodePoolRequest: { node_pool_id: nodePoolID },
})
}),
detachNodePool: (clusterID: string, nodePoolID: string) =>
withRefresh(async () => {
return await clusters.detachNodePool({ clusterID, nodePoolID })
}),
// --- metadata ---
createClusterMetadata: (clusterID: string, key: string, value: string) =>
withRefresh(async () => {
return await clusterMetadata.createClusterMetadata({
clusterID,
createClusterMetadataRequest: { key, value },
})
}),
// --- cluster runs / actions ---
listClusterRuns: (clusterID: string) =>
withRefresh(async () => {
return await clusterRuns.listClusterRuns({ clusterID })
}),
getClusterRun: (clusterID: string, runID: string) =>
withRefresh(async () => {
return await clusterRuns.getClusterRun({ clusterID, runID })
}),
runClusterAction: (clusterID: string, actionID: string) =>
withRefresh(async () => {
return await clusterRuns.runClusterAction({ clusterID, actionID })
}),
}