Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,79 @@ export const openapi: Swagger.SwaggerV3 = {
},
components: {
schemas: {
DeploymentVariableValue: {
BaseVariableValue: {
type: "object",
properties: {
id: { type: "string", format: "uuid" },
value: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object", additionalProperties: true },
],
},
sensitive: { type: "boolean" },
resourceSelector: {
type: "object",
additionalProperties: true,
nullable: true,
},
valueType: { type: "string", enum: ["direct", "reference"] },
reference: { type: "string", nullable: true },
path: { type: "array", items: { type: "string" }, nullable: true },
defaultValue: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object", additionalProperties: true },
],
nullable: true,
},
default: { type: "boolean" },
},
required: ["id", "resourceSelector", "valueType"],
},
DeploymentVariableDirectValue: {
allOf: [
{ $ref: "#/components/schemas/BaseVariableValue" },
{
type: "object",
properties: {
valueType: { type: "string", enum: ["direct"] },
value: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object" },
{ type: "array" },
],
},
sensitive: { type: "boolean" },
},
required: ["value", "valueType"],
},
],
},
DeploymentVariableReferenceValue: {
allOf: [
{ $ref: "#/components/schemas/BaseVariableValue" },
{
type: "object",
properties: {
valueType: { type: "string", enum: ["reference"] },
reference: { type: "string" },
path: { type: "array", items: { type: "string" } },
defaultValue: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object" },
{ type: "array" },
],
},
},
required: ["reference", "path", "valueType"],
},
],
},
VariableValue: {
oneOf: [
{ $ref: "#/components/schemas/DeploymentVariableDirectValue" },
{ $ref: "#/components/schemas/DeploymentVariableReferenceValue" },
],
},
DeploymentVariableValue: {
allOf: [
{ $ref: "#/components/schemas/VariableValue" },
{
type: "object",
properties: {
id: { type: "string", format: "uuid" },
},
required: ["id"],
},
],
},
DeploymentVariable: {
type: "object",
Expand Down Expand Up @@ -140,44 +181,19 @@ export const openapi: Swagger.SwaggerV3 = {
values: {
type: "array",
items: {
type: "object",
properties: {
value: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object", additionalProperties: true },
],
},
sensitive: { type: "boolean" },
resourceSelector: {
allOf: [
{ $ref: "#/components/schemas/VariableValue" },
{
type: "object",
additionalProperties: true,
nullable: true,
},
default: { type: "boolean" },
valueType: {
type: "string",
enum: ["direct", "reference"],
},
reference: { type: "string", nullable: true },
path: {
type: "array",
items: { type: "string" },
nullable: true,
},
defaultValue: {
oneOf: [
{ type: "string" },
{ type: "number" },
{ type: "boolean" },
{ type: "object", additionalProperties: true },
],
nullable: true,
properties: {
resourceSelector: {
type: "object",
additionalProperties: true,
nullable: true,
},
},
},
},
required: ["valueType"],
],
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Tx } from "@ctrlplane/db";
import type { z } from "zod";
import { NextResponse } from "next/server";
import { CREATED, INTERNAL_SERVER_ERROR, NOT_FOUND } from "http-status";
import { isPresent } from "ts-is-present";

import { eq, takeFirst } from "@ctrlplane/db";
import * as schema from "@ctrlplane/db/schema";
Expand All @@ -18,6 +19,14 @@ const log = logger.child({
route: "/v1/deployments/[deploymentId]/variables",
});

const resolveDirectValue = (val: schema.DeploymentVariableValueDirect) => {
const { id, value, valueType, sensitive, resourceSelector } = val;
const strVal =
typeof value === "object" ? JSON.stringify(value) : String(value);
const resolvedValue = sensitive ? variablesAES256().decrypt(strVal) : value;
return { id, value: resolvedValue, valueType, resourceSelector, sensitive };
};

export const GET = request()
.use(authn)
.use(
Expand Down Expand Up @@ -48,19 +57,17 @@ export const GET = request()

const variables = variablesResult.map((v) => {
const { values, defaultValueId, deploymentId: _, ...rest } = v;
const resolvedValues = values.map((val) => {
const { id, value, sensitive, resourceSelector } = val;
const strVal = String(value);
const resolvedValue = sensitive
? variablesAES256().decrypt(strVal)
: strVal;
return {
id,
value: resolvedValue,
resourceSelector,
sensitive,
};
});
const resolvedValues = values
.map((val) => {
const isDirect = schema.isDeploymentVariableValueDirect(val);
if (isDirect) return resolveDirectValue(val);
const isReference =
schema.isDeploymentVariableValueReference(val);
if (isReference) return val;
log.error("Invalid variable value type", { value: val });
return null;
})
.filter(isPresent);

const defaultValue = resolvedValues.find(
(v) => v.id === defaultValueId,
Expand Down
77 changes: 28 additions & 49 deletions e2e/api/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -910,34 +910,36 @@ export interface components {
*/
longitude: number;
};
DeploymentVariableValue: {
/** Format: uuid */
id: string;
value?:
| string
| number
| boolean
| {
[key: string]: unknown;
};
sensitive?: boolean;
resourceSelector: {
BaseVariableValue: {
resourceSelector?: {
[key: string]: unknown;
} | null;
default?: boolean;
};
DeploymentVariableDirectValue: components["schemas"]["BaseVariableValue"] & {
/** @enum {string} */
valueType: "direct";
value: string | number | boolean | Record<string, never> | unknown[];
sensitive?: boolean;
};
DeploymentVariableReferenceValue: components["schemas"]["BaseVariableValue"] & {
/** @enum {string} */
valueType: "direct" | "reference";
reference?: string | null;
path?: string[] | null;
valueType: "reference";
reference: string;
path: string[];
defaultValue?:
| (
| string
| number
| boolean
| {
[key: string]: unknown;
}
)
| null;
| string
| number
| boolean
| Record<string, never>
| unknown[];
};
VariableValue:
| components["schemas"]["DeploymentVariableDirectValue"]
| components["schemas"]["DeploymentVariableReferenceValue"];
DeploymentVariableValue: components["schemas"]["VariableValue"] & {
/** Format: uuid */
id: string;
};
DeploymentVariable: {
/** Format: uuid */
Expand Down Expand Up @@ -1978,34 +1980,11 @@ export interface operations {
config: {
[key: string]: unknown;
};
values?: {
value?:
| string
| number
| boolean
| {
[key: string]: unknown;
};
sensitive?: boolean;
values?: (components["schemas"]["VariableValue"] & {
resourceSelector?: {
[key: string]: unknown;
} | null;
default?: boolean;
/** @enum {string} */
valueType?: "direct" | "reference";
reference?: string | null;
path?: string[] | null;
defaultValue?:
| (
| string
| number
| boolean
| {
[key: string]: unknown;
}
)
| null;
}[];
})[];
};
};
};
Expand Down
42 changes: 32 additions & 10 deletions e2e/tests/api/deployment-variable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ test.describe("Deployment Variables API", () => {
type: "string",
inputType: "text",
},
values: [{ value: valueA }, { value: valueB }],
values: [
{ value: valueA, valueType: "direct" },
{ value: valueB, valueType: "direct" },
],
},
},
);
Expand Down Expand Up @@ -126,8 +129,14 @@ test.describe("Deployment Variables API", () => {

const receivedValues = receivedVariable.values;
expect(receivedValues.length).toBe(2);
const receivedValueA = receivedValues[0]!.value;
const receivedValueB = receivedValues[1]!.value;
const receivedValueA =
receivedValues[0]!.valueType === "direct"
? receivedValues[0]!.value
: receivedValues[0]!.defaultValue;
const receivedValueB =
receivedValues[1]!.valueType === "direct"
? receivedValues[1]!.value
: receivedValues[1]!.defaultValue;
expect(receivedValueA).toBe(valueA);
expect(receivedValueB).toBe(valueB);
});
Expand Down Expand Up @@ -155,7 +164,10 @@ test.describe("Deployment Variables API", () => {
type: "string",
inputType: "text",
},
values: [{ value: valueA }, { value: valueB, default: true }],
values: [
{ value: valueA, valueType: "direct" },
{ value: valueB, valueType: "direct", default: true },
],
},
},
);
Expand Down Expand Up @@ -186,13 +198,23 @@ test.describe("Deployment Variables API", () => {

const receivedValues = receivedVariable.values;
expect(receivedValues.length).toBe(2);
const receivedValueA = receivedValues[0]!.value;
const receivedValueB = receivedValues[1]!.value;
const receivedValueA =
receivedValues[0]!.valueType === "direct"
? receivedValues[0]!.value
: receivedValues[0]!.defaultValue;
const receivedValueB =
receivedValues[1]!.valueType === "direct"
? receivedValues[1]!.value
: receivedValues[1]!.defaultValue;
expect(receivedValueA).toBe(valueA);
expect(receivedValueB).toBe(valueB);

const receivedDefaultValue = receivedVariable.defaultValue;
expect(receivedDefaultValue?.value).toBe(valueB);
const receivedDefaultValue =
receivedValues[1]!.valueType === "direct"
? receivedValues[1]!.value
: receivedValues[1]!.defaultValue;

expect(receivedDefaultValue).toBe(valueB);
});

test("shoudl fail if more than one default value is provided", async ({
Expand All @@ -219,8 +241,8 @@ test.describe("Deployment Variables API", () => {
inputType: "text",
},
values: [
{ value: valueA, default: true },
{ value: valueB, default: true },
{ value: valueA, valueType: "direct", default: true },
{ value: valueB, valueType: "direct", default: true },
],
},
},
Expand Down
Loading
Loading