Skip to content

Commit 06ebf2a

Browse files
chore: resource variable router
1 parent b65da17 commit 06ebf2a

File tree

6 files changed

+274
-4
lines changed

6 files changed

+274
-4
lines changed

apps/api/openapi/openapi.json

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,25 @@
12631263
],
12641264
"type": "object"
12651265
},
1266+
"ResourceVariable": {
1267+
"properties": {
1268+
"key": {
1269+
"type": "string"
1270+
},
1271+
"resourceId": {
1272+
"type": "string"
1273+
},
1274+
"value": {
1275+
"$ref": "#/components/schemas/Value"
1276+
}
1277+
},
1278+
"required": [
1279+
"resourceId",
1280+
"key",
1281+
"value"
1282+
],
1283+
"type": "object"
1284+
},
12661285
"Selector": {
12671286
"oneOf": [
12681287
{
@@ -4969,6 +4988,117 @@
49694988
]
49704989
}
49714990
},
4991+
"/v1/workspaces/{workspaceId}/resources/identifier/{identifier}/variables": {
4992+
"get": {
4993+
"description": "Returns a list of variables for a resource",
4994+
"operationId": "getVariablesForResource",
4995+
"parameters": [
4996+
{
4997+
"description": "ID of the workspace",
4998+
"in": "path",
4999+
"name": "workspaceId",
5000+
"required": true,
5001+
"schema": {
5002+
"type": "string"
5003+
}
5004+
},
5005+
{
5006+
"description": "Identifier of the resource",
5007+
"in": "path",
5008+
"name": "identifier",
5009+
"required": true,
5010+
"schema": {
5011+
"type": "string"
5012+
}
5013+
},
5014+
{
5015+
"description": "Maximum number of items to return",
5016+
"in": "query",
5017+
"name": "limit",
5018+
"required": false,
5019+
"schema": {
5020+
"default": 50,
5021+
"maximum": 1000,
5022+
"minimum": 1,
5023+
"type": "integer"
5024+
}
5025+
},
5026+
{
5027+
"description": "Number of items to skip",
5028+
"in": "query",
5029+
"name": "offset",
5030+
"required": false,
5031+
"schema": {
5032+
"default": 0,
5033+
"minimum": 0,
5034+
"type": "integer"
5035+
}
5036+
}
5037+
],
5038+
"responses": {
5039+
"200": {
5040+
"content": {
5041+
"application/json": {
5042+
"schema": {
5043+
"properties": {
5044+
"items": {
5045+
"items": {
5046+
"$ref": "#/components/schemas/ResourceVariable"
5047+
},
5048+
"type": "array"
5049+
},
5050+
"limit": {
5051+
"description": "Maximum number of items returned",
5052+
"type": "integer"
5053+
},
5054+
"offset": {
5055+
"description": "Number of items skipped",
5056+
"type": "integer"
5057+
},
5058+
"total": {
5059+
"description": "Total number of items available",
5060+
"type": "integer"
5061+
}
5062+
},
5063+
"required": [
5064+
"items",
5065+
"total",
5066+
"limit",
5067+
"offset"
5068+
],
5069+
"type": "object"
5070+
}
5071+
}
5072+
},
5073+
"description": "The requested variables"
5074+
},
5075+
"400": {
5076+
"content": {
5077+
"application/json": {
5078+
"schema": {
5079+
"$ref": "#/components/schemas/ErrorResponse"
5080+
}
5081+
}
5082+
},
5083+
"description": "Invalid request"
5084+
},
5085+
"404": {
5086+
"content": {
5087+
"application/json": {
5088+
"schema": {
5089+
"$ref": "#/components/schemas/ErrorResponse"
5090+
}
5091+
}
5092+
},
5093+
"description": "Resource not found"
5094+
}
5095+
},
5096+
"summary": "Get variables for a resource",
5097+
"tags": [
5098+
"Resources"
5099+
]
5100+
}
5101+
},
49725102
"/v1/workspaces/{workspaceId}/systems": {
49735103
"get": {
49745104
"operationId": "listSystems",

apps/api/openapi/paths/resources.jsonnet

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,21 @@ local openapi = import '../lib/openapi.libsonnet';
3030
responses: openapi.okResponse(openapi.schemaRef('Resource')),
3131
},
3232
},
33+
'/v1/workspaces/{workspaceId}/resources/identifier/{identifier}/variables': {
34+
get: {
35+
tags: ['Resources'],
36+
summary: 'Get variables for a resource',
37+
operationId: 'getVariablesForResource',
38+
description: 'Returns a list of variables for a resource',
39+
parameters: [
40+
openapi.workspaceIdParam(),
41+
openapi.identifierParam(),
42+
openapi.limitParam(),
43+
openapi.offsetParam(),
44+
],
45+
responses: openapi.paginatedResponse(openapi.schemaRef('ResourceVariable'), 'The requested variables') +
46+
openapi.notFoundResponse() +
47+
openapi.badRequestResponse(),
48+
},
49+
}
3350
}

apps/api/openapi/schemas/resources.jsonnet

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
local openapi = import '../lib/openapi.libsonnet';
2+
13
{
24
Resource: {
35
type: 'object',
@@ -32,4 +34,13 @@
3234
},
3335
},
3436
},
37+
ResourceVariable: {
38+
type: 'object',
39+
required: ['resourceId', 'key', 'value'],
40+
properties: {
41+
resourceId: { type: 'string' },
42+
key: { type: 'string' },
43+
value: openapi.schemaRef('Value'),
44+
},
45+
},
3546
}

apps/api/src/routes/v1/workspaces/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { relationshipRulesRouter } from "./relationship-rules.js";
1919
import { releaseTargetsRouter } from "./release-targets.js";
2020
import { releaseRouter } from "./releases.js";
2121
import { resourceProvidersRouter } from "./resource-providers.js";
22-
import { listResources } from "./resources.js";
22+
import { resourceRouter } from "./resources.js";
2323
import { systemRouter } from "./systems.js";
2424

2525
/**
@@ -33,7 +33,7 @@ export const createWorkspacesRouter = (): Router =>
3333
.get("/:workspaceId", asyncHandler(getWorkspace))
3434
.patch("/:workspaceId", asyncHandler(updateWorkspace))
3535
.delete("/:workspaceId", asyncHandler(deleteWorkspace))
36-
.get("/:workspaceId/resources", asyncHandler(listResources))
36+
.use("/:workspaceId/resources", resourceRouter)
3737
.use("/:workspaceId/systems", systemRouter)
3838
.use("/:workspaceId/resource-providers", resourceProvidersRouter)
3939
.use("/:workspaceId/deployments", deploymentsRouter)

apps/api/src/routes/v1/workspaces/resources.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { AsyncTypedHandler } from "@/types/api.js";
2+
import { ApiError, asyncHandler } from "@/types/api.js";
3+
import { Router } from "express";
24

35
import { getClientFor } from "@ctrlplane/workspace-engine-sdk";
46

5-
export const listResources: AsyncTypedHandler<
7+
const listResources: AsyncTypedHandler<
68
"/v1/workspaces/{workspaceId}/resources",
79
"get"
810
> = async (req, res) => {
@@ -33,7 +35,7 @@ export const listResources: AsyncTypedHandler<
3335
res.status(200).json(result.data);
3436
};
3537

36-
export const getResourceByIdentifier: AsyncTypedHandler<
38+
const getResourceByIdentifier: AsyncTypedHandler<
3739
"/v1/workspaces/{workspaceId}/resources/identifier/{identifier}",
3840
"get"
3941
> = async (req, res) => {
@@ -51,3 +53,32 @@ export const getResourceByIdentifier: AsyncTypedHandler<
5153

5254
res.status(200).json(result.data);
5355
};
56+
57+
const getVariablesForResource: AsyncTypedHandler<
58+
"/v1/workspaces/{workspaceId}/resources/identifier/{identifier}/variables",
59+
"get"
60+
> = async (req, res) => {
61+
const { workspaceId, identifier } = req.params;
62+
const { limit, offset } = req.query;
63+
64+
const result = await getClientFor(workspaceId).GET(
65+
"/v1/workspaces/{workspaceId}/resources/{resourceIdentifier}/variables",
66+
{
67+
params: { path: { workspaceId, resourceIdentifier: identifier } },
68+
query: { limit, offset },
69+
},
70+
);
71+
72+
if (result.error != null)
73+
throw new ApiError(
74+
result.error.error ?? "Failed to get variables for resource",
75+
500,
76+
);
77+
78+
res.status(200).json(result.data);
79+
};
80+
81+
export const resourceRouter = Router({ mergeParams: true })
82+
.get("/", asyncHandler(listResources))
83+
.get("/:identifier", asyncHandler(getResourceByIdentifier))
84+
.get("/:identifier/variables", asyncHandler(getVariablesForResource));

apps/api/src/types/openapi.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,26 @@ export interface paths {
625625
patch?: never;
626626
trace?: never;
627627
};
628+
"/v1/workspaces/{workspaceId}/resources/identifier/{identifier}/variables": {
629+
parameters: {
630+
query?: never;
631+
header?: never;
632+
path?: never;
633+
cookie?: never;
634+
};
635+
/**
636+
* Get variables for a resource
637+
* @description Returns a list of variables for a resource
638+
*/
639+
get: operations["getVariablesForResource"];
640+
put?: never;
641+
post?: never;
642+
delete?: never;
643+
options?: never;
644+
head?: never;
645+
patch?: never;
646+
trace?: never;
647+
};
628648
"/v1/workspaces/{workspaceId}/systems": {
629649
parameters: {
630650
query?: never;
@@ -1057,6 +1077,11 @@ export interface components {
10571077
updatedAt?: string;
10581078
version: string;
10591079
};
1080+
ResourceVariable: {
1081+
key: string;
1082+
resourceId: string;
1083+
value: components["schemas"]["Value"];
1084+
};
10601085
Selector: components["schemas"]["JsonSelector"] | components["schemas"]["CelSelector"];
10611086
SensitiveValue: {
10621087
valueHash: string;
@@ -3307,6 +3332,62 @@ export interface operations {
33073332
};
33083333
};
33093334
};
3335+
getVariablesForResource: {
3336+
parameters: {
3337+
query?: {
3338+
/** @description Maximum number of items to return */
3339+
limit?: number;
3340+
/** @description Number of items to skip */
3341+
offset?: number;
3342+
};
3343+
header?: never;
3344+
path: {
3345+
/** @description ID of the workspace */
3346+
workspaceId: string;
3347+
/** @description Identifier of the resource */
3348+
identifier: string;
3349+
};
3350+
cookie?: never;
3351+
};
3352+
requestBody?: never;
3353+
responses: {
3354+
/** @description The requested variables */
3355+
200: {
3356+
headers: {
3357+
[name: string]: unknown;
3358+
};
3359+
content: {
3360+
"application/json": {
3361+
items: components["schemas"]["ResourceVariable"][];
3362+
/** @description Maximum number of items returned */
3363+
limit: number;
3364+
/** @description Number of items skipped */
3365+
offset: number;
3366+
/** @description Total number of items available */
3367+
total: number;
3368+
};
3369+
};
3370+
};
3371+
/** @description Invalid request */
3372+
400: {
3373+
headers: {
3374+
[name: string]: unknown;
3375+
};
3376+
content: {
3377+
"application/json": components["schemas"]["ErrorResponse"];
3378+
};
3379+
};
3380+
/** @description Resource not found */
3381+
404: {
3382+
headers: {
3383+
[name: string]: unknown;
3384+
};
3385+
content: {
3386+
"application/json": components["schemas"]["ErrorResponse"];
3387+
};
3388+
};
3389+
};
3390+
};
33103391
listSystems: {
33113392
parameters: {
33123393
query?: {

0 commit comments

Comments
 (0)