@tailor-platform/sdk 0.8.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/cli/api.d.mts +12 -11
- package/dist/cli/api.mjs +1 -1
- package/dist/cli/index.mjs +4 -5
- package/dist/configure/index.d.mts +2 -2
- package/dist/{index-Bwrm8M8p.d.mts → index-DHpKRtq3.d.mts} +1 -1
- package/dist/{token-B9zkxSMS.mjs → token-DwKmpi9i.mjs} +726 -301
- package/dist/{types-BP7g8Bh3.d.mts → types-CPcmGK_X.d.mts} +8 -8
- package/dist/utils/test/index.d.mts +2 -2
- package/docs/cli-reference.md +1 -0
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ import * as os from "node:os";
|
|
|
21
21
|
import { parseTOML, parseYAML, stringifyYAML } from "confbox";
|
|
22
22
|
import { xdgConfig } from "xdg-basedir";
|
|
23
23
|
import { fromJson } from "@bufbuild/protobuf";
|
|
24
|
+
import chalk from "chalk";
|
|
24
25
|
import { spawn } from "node:child_process";
|
|
25
26
|
import { glob } from "node:fs/promises";
|
|
26
27
|
import chokidar from "chokidar";
|
|
@@ -190,6 +191,7 @@ var ExecutorService = class {
|
|
|
190
191
|
this.config = config;
|
|
191
192
|
}
|
|
192
193
|
async loadExecutors() {
|
|
194
|
+
if (Object.keys(this.executors).length > 0) return this.executors;
|
|
193
195
|
if (!this.config.files || this.config.files.length === 0) return;
|
|
194
196
|
const executorFiles = loadFilesWithIgnores(this.config);
|
|
195
197
|
console.log("");
|
|
@@ -275,6 +277,7 @@ var ResolverService = class {
|
|
|
275
277
|
this.config = config;
|
|
276
278
|
}
|
|
277
279
|
async loadResolvers() {
|
|
280
|
+
if (Object.keys(this.resolvers).length > 0) return;
|
|
278
281
|
if (!this.config.files || this.config.files.length === 0) return;
|
|
279
282
|
const resolverFiles = loadFilesWithIgnores(this.config);
|
|
280
283
|
console.log("");
|
|
@@ -867,10 +870,11 @@ var EnumProcessor = class {
|
|
|
867
870
|
/**
|
|
868
871
|
* Generate enum constant definitions from collected metadata.
|
|
869
872
|
*/
|
|
870
|
-
static
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
const
|
|
873
|
+
static generateUnifiedEnumConstants(allEnums) {
|
|
874
|
+
if (allEnums.length === 0) return "";
|
|
875
|
+
const enumMap = /* @__PURE__ */ new Map();
|
|
876
|
+
for (const enumDef of allEnums) enumMap.set(enumDef.name, enumDef);
|
|
877
|
+
const enumDefs = Array.from(enumMap.values()).map((e) => {
|
|
874
878
|
const members = e.values.map((v) => {
|
|
875
879
|
return ` "${v.value.replace(/[-\s]/g, "_")}": "${v.value}"`;
|
|
876
880
|
}).join(",\n");
|
|
@@ -920,17 +924,27 @@ var EnumConstantsGenerator = class {
|
|
|
920
924
|
processResolver() {}
|
|
921
925
|
processExecutor() {}
|
|
922
926
|
async processTailorDBNamespace(args) {
|
|
923
|
-
|
|
927
|
+
const allEnums = [];
|
|
928
|
+
for (const enumConstantMetadata of Object.values(args.types)) allEnums.push(...enumConstantMetadata.enums);
|
|
929
|
+
return {
|
|
930
|
+
namespace: args.namespace,
|
|
931
|
+
enums: allEnums
|
|
932
|
+
};
|
|
924
933
|
}
|
|
925
934
|
processIdProvider() {}
|
|
926
935
|
processAuth() {}
|
|
927
936
|
processStaticWebsite() {}
|
|
928
937
|
aggregate(args) {
|
|
929
938
|
const files = [];
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
939
|
+
const allEnums = [];
|
|
940
|
+
for (const input of args.inputs) for (const nsResult of input.tailordb) if (nsResult.types && nsResult.types.enums.length > 0) allEnums.push(...nsResult.types.enums);
|
|
941
|
+
if (allEnums.length > 0) {
|
|
942
|
+
const content = EnumProcessor.generateUnifiedEnumConstants(allEnums);
|
|
943
|
+
files.push({
|
|
944
|
+
path: this.options.distPath,
|
|
945
|
+
content
|
|
946
|
+
});
|
|
947
|
+
}
|
|
934
948
|
return { files };
|
|
935
949
|
}
|
|
936
950
|
};
|
|
@@ -1083,7 +1097,7 @@ var FileUtilsGenerator = class {
|
|
|
1083
1097
|
/**
|
|
1084
1098
|
* Processor that converts a ParsedTailorDBType into Kysely type metadata.
|
|
1085
1099
|
*/
|
|
1086
|
-
var TypeProcessor = class
|
|
1100
|
+
var TypeProcessor = class {
|
|
1087
1101
|
/**
|
|
1088
1102
|
* Convert a ParsedTailorDBType into KyselyTypeMetadata.
|
|
1089
1103
|
*/
|
|
@@ -1221,49 +1235,52 @@ var TypeProcessor = class TypeProcessor {
|
|
|
1221
1235
|
usedUtilityTypes: aggregatedUtilityTypes
|
|
1222
1236
|
};
|
|
1223
1237
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1238
|
+
/**
|
|
1239
|
+
* Generate unified types file from multiple namespaces.
|
|
1240
|
+
*/
|
|
1241
|
+
static generateUnifiedTypes(namespaceData) {
|
|
1242
|
+
if (namespaceData.length === 0) return "";
|
|
1243
|
+
const globalUsedUtilityTypes = namespaceData.reduce((acc, ns) => ({
|
|
1244
|
+
Timestamp: acc.Timestamp || ns.usedUtilityTypes.Timestamp,
|
|
1245
|
+
Serial: acc.Serial || ns.usedUtilityTypes.Serial
|
|
1228
1246
|
}), {
|
|
1229
1247
|
Timestamp: false,
|
|
1230
1248
|
Serial: false
|
|
1231
1249
|
});
|
|
1232
1250
|
const utilityTypeDeclarations = [];
|
|
1233
|
-
if (
|
|
1251
|
+
if (globalUsedUtilityTypes.Timestamp) utilityTypeDeclarations.push(`type Timestamp = ColumnType<Date, Date | string, Date | string>;`);
|
|
1234
1252
|
utilityTypeDeclarations.push(ml`
|
|
1235
1253
|
type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
|
|
1236
1254
|
? ColumnType<S, I | undefined, U>
|
|
1237
1255
|
: ColumnType<T, T | undefined, T>;
|
|
1238
1256
|
`);
|
|
1239
|
-
if (
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
import { TailordbDialect } from "@tailor-platform/function-kysely-tailordb";
|
|
1257
|
+
if (globalUsedUtilityTypes.Serial) utilityTypeDeclarations.push(`type Serial<T = string | number> = ColumnType<T, never, never>;`);
|
|
1258
|
+
const importsSection = ml`
|
|
1259
|
+
import { type ColumnType, Kysely } from "kysely";
|
|
1260
|
+
import { TailordbDialect } from "@tailor-platform/function-kysely-tailordb";
|
|
1244
1261
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1262
|
+
${utilityTypeDeclarations.join("\n")}
|
|
1263
|
+
`;
|
|
1264
|
+
const namespaceInterface = `export interface Namespace {\n${namespaceData.map(({ namespace, types }) => {
|
|
1265
|
+
const typeDefsWithIndent = types.map((type) => {
|
|
1266
|
+
return type.typeDef.split("\n").map((line) => line.trim() ? ` ${line}` : "").join("\n");
|
|
1267
|
+
}).join("\n\n");
|
|
1268
|
+
return ` "${namespace}": {\n${typeDefsWithIndent}\n }`;
|
|
1269
|
+
}).join(",\n")}\n}`;
|
|
1270
|
+
const getDBFunction = ml`
|
|
1271
|
+
export function getDB<const N extends keyof Namespace>(namespace: N): Kysely<Namespace[N]> {
|
|
1272
|
+
const client = new tailordb.Client({ namespace });
|
|
1273
|
+
return new Kysely<Namespace[N]>({ dialect: new TailordbDialect(client) });
|
|
1274
|
+
}
|
|
1253
1275
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1276
|
+
export type DB<N extends keyof Namespace = keyof Namespace> = ReturnType<typeof getDB<N>>;
|
|
1277
|
+
`;
|
|
1278
|
+
return [
|
|
1279
|
+
importsSection,
|
|
1280
|
+
namespaceInterface,
|
|
1281
|
+
getDBFunction
|
|
1256
1282
|
].join("\n\n") + "\n";
|
|
1257
1283
|
}
|
|
1258
|
-
/**
|
|
1259
|
-
* Generate the Namespace interface.
|
|
1260
|
-
*/
|
|
1261
|
-
static generateNamespaceInterface(types, namespace) {
|
|
1262
|
-
const typeDefsWithIndent = types.map((type) => {
|
|
1263
|
-
return type.typeDef.split("\n").map((line) => line.trim() ? ` ${line}` : "").join("\n");
|
|
1264
|
-
}).join("\n\n");
|
|
1265
|
-
return `export interface Namespace {\n "${namespace}": {\n${typeDefsWithIndent}\n }\n}`;
|
|
1266
|
-
}
|
|
1267
1284
|
};
|
|
1268
1285
|
|
|
1269
1286
|
//#endregion
|
|
@@ -1284,14 +1301,31 @@ var KyselyGenerator = class {
|
|
|
1284
1301
|
processResolver() {}
|
|
1285
1302
|
processExecutor() {}
|
|
1286
1303
|
async processTailorDBNamespace(args) {
|
|
1287
|
-
|
|
1304
|
+
const typesList = Object.values(args.types);
|
|
1305
|
+
const usedUtilityTypes = typesList.reduce((acc, type) => ({
|
|
1306
|
+
Timestamp: acc.Timestamp || type.usedUtilityTypes.Timestamp,
|
|
1307
|
+
Serial: acc.Serial || type.usedUtilityTypes.Serial
|
|
1308
|
+
}), {
|
|
1309
|
+
Timestamp: false,
|
|
1310
|
+
Serial: false
|
|
1311
|
+
});
|
|
1312
|
+
return {
|
|
1313
|
+
namespace: args.namespace,
|
|
1314
|
+
types: typesList,
|
|
1315
|
+
usedUtilityTypes
|
|
1316
|
+
};
|
|
1288
1317
|
}
|
|
1289
1318
|
aggregate(args) {
|
|
1290
1319
|
const files = [];
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1320
|
+
const allNamespaceData = [];
|
|
1321
|
+
for (const input of args.inputs) for (const nsResult of input.tailordb) if (nsResult.types && nsResult.types.types.length > 0) allNamespaceData.push(nsResult.types);
|
|
1322
|
+
if (allNamespaceData.length > 0) {
|
|
1323
|
+
const content = TypeProcessor.generateUnifiedTypes(allNamespaceData);
|
|
1324
|
+
files.push({
|
|
1325
|
+
path: this.options.distPath,
|
|
1326
|
+
content
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1295
1329
|
return { files };
|
|
1296
1330
|
}
|
|
1297
1331
|
};
|
|
@@ -2223,6 +2257,15 @@ const file_tailor_v1_service = /* @__PURE__ */ fileDesc("Chd0YWlsb3IvdjEvc2Vydml
|
|
|
2223
2257
|
*/
|
|
2224
2258
|
const OperatorService = /* @__PURE__ */ serviceDesc(file_tailor_v1_service, 0);
|
|
2225
2259
|
|
|
2260
|
+
//#endregion
|
|
2261
|
+
//#region src/cli/package-json.ts
|
|
2262
|
+
let packageJson = null;
|
|
2263
|
+
async function readPackageJson() {
|
|
2264
|
+
if (packageJson) return packageJson;
|
|
2265
|
+
packageJson = await readPackageJSON(import.meta.url);
|
|
2266
|
+
return packageJson;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2226
2269
|
//#endregion
|
|
2227
2270
|
//#region src/cli/client.ts
|
|
2228
2271
|
const baseUrl = process.env.PLATFORM_URL ?? "https://api.tailor.tech";
|
|
@@ -2247,7 +2290,7 @@ async function userAgentInterceptor() {
|
|
|
2247
2290
|
};
|
|
2248
2291
|
}
|
|
2249
2292
|
async function userAgent() {
|
|
2250
|
-
return `tailor-sdk/${(await
|
|
2293
|
+
return `tailor-sdk/${(await readPackageJson()).version ?? "unknown"}`;
|
|
2251
2294
|
}
|
|
2252
2295
|
async function bearerTokenInterceptor(accessToken) {
|
|
2253
2296
|
return (next) => async (req) => {
|
|
@@ -2509,6 +2552,24 @@ function loadConfigPath(configPath) {
|
|
|
2509
2552
|
return "tailor.config.ts";
|
|
2510
2553
|
}
|
|
2511
2554
|
|
|
2555
|
+
//#endregion
|
|
2556
|
+
//#region src/cli/apply/services/label.ts
|
|
2557
|
+
function trnPrefix(workspaceId) {
|
|
2558
|
+
return `trn:v1:workspace:${workspaceId}`;
|
|
2559
|
+
}
|
|
2560
|
+
const sdkNameLabelKey = "sdk-name";
|
|
2561
|
+
async function buildMetaRequest(trn$7, appName) {
|
|
2562
|
+
const packageJson$1 = await readPackageJson();
|
|
2563
|
+
const sdkVersion = packageJson$1.version ? `v${packageJson$1.version.replace(/\./g, "-")}` : "unknown";
|
|
2564
|
+
return {
|
|
2565
|
+
trn: trn$7,
|
|
2566
|
+
labels: {
|
|
2567
|
+
[sdkNameLabelKey]: appName,
|
|
2568
|
+
"sdk-version": sdkVersion
|
|
2569
|
+
}
|
|
2570
|
+
};
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2512
2573
|
//#endregion
|
|
2513
2574
|
//#region src/cli/apply/services/index.ts
|
|
2514
2575
|
var ChangeSet = class {
|
|
@@ -2538,14 +2599,21 @@ var ChangeSet = class {
|
|
|
2538
2599
|
async function applyApplication(client, changeSet, phase = "create-update") {
|
|
2539
2600
|
if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
|
|
2540
2601
|
create.request.cors = await resolveStaticWebsiteUrls(client, create.request.workspaceId, create.request.cors, "CORS");
|
|
2541
|
-
|
|
2602
|
+
await client.createApplication(create.request);
|
|
2603
|
+
await client.setMetadata(create.metaRequest);
|
|
2542
2604
|
}), ...changeSet.updates.map(async (update) => {
|
|
2543
2605
|
update.request.cors = await resolveStaticWebsiteUrls(client, update.request.workspaceId, update.request.cors, "CORS");
|
|
2544
|
-
|
|
2606
|
+
await client.updateApplication(update.request);
|
|
2607
|
+
await client.setMetadata(update.metaRequest);
|
|
2545
2608
|
})]);
|
|
2546
|
-
else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) =>
|
|
2609
|
+
else if (phase === "delete") await Promise.all(changeSet.deletes.map(async (del) => {
|
|
2610
|
+
await client.deleteApplication(del.request);
|
|
2611
|
+
}));
|
|
2547
2612
|
}
|
|
2548
|
-
|
|
2613
|
+
function trn$6(workspaceId, name) {
|
|
2614
|
+
return `trn:v1:workspace:${workspaceId}:application:${name}`;
|
|
2615
|
+
}
|
|
2616
|
+
async function planApplication({ client, workspaceId, application }) {
|
|
2549
2617
|
const changeSet = new ChangeSet("Applications");
|
|
2550
2618
|
const existingApplications = await fetchAll(async (pageToken) => {
|
|
2551
2619
|
try {
|
|
@@ -2559,55 +2627,41 @@ async function planApplication(client, workspaceId, application) {
|
|
|
2559
2627
|
throw error;
|
|
2560
2628
|
}
|
|
2561
2629
|
});
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2630
|
+
let authNamespace;
|
|
2631
|
+
let authIdpConfigName;
|
|
2632
|
+
if (application.authService && application.authService.config) {
|
|
2633
|
+
authNamespace = application.authService.config.name;
|
|
2634
|
+
const idProvider = application.authService.config.idProvider;
|
|
2635
|
+
if (idProvider) authIdpConfigName = idProvider.name;
|
|
2636
|
+
}
|
|
2637
|
+
const metaRequest = await buildMetaRequest(trn$6(workspaceId, application.name), application.name);
|
|
2638
|
+
if (existingApplications.some((app) => app.name === application.name)) changeSet.updates.push({
|
|
2639
|
+
name: application.name,
|
|
2640
|
+
request: {
|
|
2641
|
+
workspaceId,
|
|
2642
|
+
applicationName: application.name,
|
|
2643
|
+
authNamespace,
|
|
2644
|
+
authIdpConfigName,
|
|
2645
|
+
cors: application.config.cors,
|
|
2646
|
+
subgraphs: application.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
|
|
2647
|
+
allowedIpAddresses: application.config.allowedIPAddresses,
|
|
2648
|
+
disableIntrospection: application.config.disableIntrospection
|
|
2649
|
+
},
|
|
2650
|
+
metaRequest
|
|
2565
2651
|
});
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
applicationName: app.name,
|
|
2580
|
-
authNamespace,
|
|
2581
|
-
authIdpConfigName,
|
|
2582
|
-
cors: app.config.cors,
|
|
2583
|
-
subgraphs: app.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
|
|
2584
|
-
allowedIpAddresses: app.config.allowedIPAddresses,
|
|
2585
|
-
disableIntrospection: app.config.disableIntrospection
|
|
2586
|
-
}
|
|
2587
|
-
});
|
|
2588
|
-
existingNameSet.delete(app.name);
|
|
2589
|
-
} else changeSet.creates.push({
|
|
2590
|
-
name: app.name,
|
|
2591
|
-
request: {
|
|
2592
|
-
workspaceId,
|
|
2593
|
-
applicationName: app.name,
|
|
2594
|
-
authNamespace,
|
|
2595
|
-
authIdpConfigName,
|
|
2596
|
-
cors: app.config.cors,
|
|
2597
|
-
subgraphs: app.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
|
|
2598
|
-
allowedIpAddresses: app.config.allowedIPAddresses,
|
|
2599
|
-
disableIntrospection: app.config.disableIntrospection
|
|
2600
|
-
}
|
|
2601
|
-
});
|
|
2602
|
-
}
|
|
2603
|
-
existingNameSet.forEach((name) => {
|
|
2604
|
-
changeSet.deletes.push({
|
|
2605
|
-
name,
|
|
2606
|
-
request: {
|
|
2607
|
-
workspaceId,
|
|
2608
|
-
applicationName: name
|
|
2609
|
-
}
|
|
2610
|
-
});
|
|
2652
|
+
else changeSet.creates.push({
|
|
2653
|
+
name: application.name,
|
|
2654
|
+
request: {
|
|
2655
|
+
workspaceId,
|
|
2656
|
+
applicationName: application.name,
|
|
2657
|
+
authNamespace,
|
|
2658
|
+
authIdpConfigName,
|
|
2659
|
+
cors: application.config.cors,
|
|
2660
|
+
subgraphs: application.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
|
|
2661
|
+
allowedIpAddresses: application.config.allowedIPAddresses,
|
|
2662
|
+
disableIntrospection: application.config.disableIntrospection
|
|
2663
|
+
},
|
|
2664
|
+
metaRequest
|
|
2611
2665
|
});
|
|
2612
2666
|
changeSet.print();
|
|
2613
2667
|
return changeSet;
|
|
@@ -2643,9 +2697,16 @@ function idpClientVaultName(namespaceName, clientName) {
|
|
|
2643
2697
|
function idpClientSecretName(namespaceName, clientName) {
|
|
2644
2698
|
return `client-secret-${namespaceName}-${clientName}`;
|
|
2645
2699
|
}
|
|
2646
|
-
async function applyIdP(client,
|
|
2700
|
+
async function applyIdP(client, result, phase = "create-update") {
|
|
2701
|
+
const { changeSet } = result;
|
|
2647
2702
|
if (phase === "create-update") {
|
|
2648
|
-
await Promise.all([...changeSet.service.creates.map(
|
|
2703
|
+
await Promise.all([...changeSet.service.creates.map(async (create) => {
|
|
2704
|
+
await client.createIdPService(create.request);
|
|
2705
|
+
await client.setMetadata(create.metaRequest);
|
|
2706
|
+
}), ...changeSet.service.updates.map(async (update) => {
|
|
2707
|
+
await client.updateIdPService(update.request);
|
|
2708
|
+
await client.setMetadata(update.metaRequest);
|
|
2709
|
+
})]);
|
|
2649
2710
|
await Promise.all([...changeSet.client.creates.map(async (create) => {
|
|
2650
2711
|
const resp = await client.createIdPClient(create.request);
|
|
2651
2712
|
const vaultName = idpClientVaultName(create.request.namespaceName, create.request.client?.name || "");
|
|
@@ -2684,7 +2745,7 @@ async function applyIdP(client, changeSet, phase = "create-update") {
|
|
|
2684
2745
|
});
|
|
2685
2746
|
})]);
|
|
2686
2747
|
} else if (phase === "delete") {
|
|
2687
|
-
await Promise.all(changeSet.client.deletes.
|
|
2748
|
+
await Promise.all(changeSet.client.deletes.map(async (del) => {
|
|
2688
2749
|
await client.deleteIdPClient(del.request);
|
|
2689
2750
|
const vaultName = `idp-${del.request.namespaceName}-${del.request.name}`;
|
|
2690
2751
|
await client.deleteSecretManagerVault({
|
|
@@ -2695,22 +2756,32 @@ async function applyIdP(client, changeSet, phase = "create-update") {
|
|
|
2695
2756
|
await Promise.all(changeSet.service.deletes.map((del) => client.deleteIdPService(del.request)));
|
|
2696
2757
|
}
|
|
2697
2758
|
}
|
|
2698
|
-
async function planIdP(client, workspaceId, application) {
|
|
2699
|
-
const idps =
|
|
2700
|
-
|
|
2701
|
-
const serviceChangeSet = await planServices$3(client, workspaceId, idps);
|
|
2759
|
+
async function planIdP({ client, workspaceId, application }) {
|
|
2760
|
+
const idps = application.idpServices;
|
|
2761
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$3(client, workspaceId, application.name, idps);
|
|
2702
2762
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
2703
2763
|
const clientChangeSet = await planClients(client, workspaceId, idps, deletedServices);
|
|
2704
2764
|
serviceChangeSet.print();
|
|
2705
2765
|
clientChangeSet.print();
|
|
2706
2766
|
return {
|
|
2707
|
-
|
|
2708
|
-
|
|
2767
|
+
changeSet: {
|
|
2768
|
+
service: serviceChangeSet,
|
|
2769
|
+
client: clientChangeSet
|
|
2770
|
+
},
|
|
2771
|
+
conflicts,
|
|
2772
|
+
unmanaged,
|
|
2773
|
+
resourceOwners
|
|
2709
2774
|
};
|
|
2710
2775
|
}
|
|
2711
|
-
|
|
2776
|
+
function trn$5(workspaceId, name) {
|
|
2777
|
+
return `trn:v1:workspace:${workspaceId}:idp:${name}`;
|
|
2778
|
+
}
|
|
2779
|
+
async function planServices$3(client, workspaceId, appName, idps) {
|
|
2712
2780
|
const changeSet = new ChangeSet("IdP services");
|
|
2713
|
-
const
|
|
2781
|
+
const conflicts = [];
|
|
2782
|
+
const unmanaged = [];
|
|
2783
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
2784
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
2714
2785
|
try {
|
|
2715
2786
|
const { idpServices, nextPageToken } = await client.listIdPServices({
|
|
2716
2787
|
workspaceId,
|
|
@@ -2722,13 +2793,19 @@ async function planServices$3(client, workspaceId, idps) {
|
|
|
2722
2793
|
throw error;
|
|
2723
2794
|
}
|
|
2724
2795
|
});
|
|
2725
|
-
const
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2796
|
+
const existingServices = {};
|
|
2797
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
2798
|
+
if (!resource.namespace?.name) return;
|
|
2799
|
+
const { metadata } = await client.getMetadata({ trn: trn$5(workspaceId, resource.namespace.name) });
|
|
2800
|
+
existingServices[resource.namespace.name] = {
|
|
2801
|
+
resource,
|
|
2802
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
2803
|
+
};
|
|
2804
|
+
}));
|
|
2730
2805
|
for (const idp of idps) {
|
|
2731
2806
|
const namespaceName = idp.name;
|
|
2807
|
+
const existing = existingServices[namespaceName];
|
|
2808
|
+
const metaRequest = await buildMetaRequest(trn$5(workspaceId, namespaceName), appName);
|
|
2732
2809
|
let authorization;
|
|
2733
2810
|
switch (idp.authorization) {
|
|
2734
2811
|
case "insecure":
|
|
@@ -2741,27 +2818,40 @@ async function planServices$3(client, workspaceId, idps) {
|
|
|
2741
2818
|
authorization = idp.authorization.cel;
|
|
2742
2819
|
break;
|
|
2743
2820
|
}
|
|
2744
|
-
if (
|
|
2821
|
+
if (existing) {
|
|
2822
|
+
if (!existing.label) unmanaged.push({
|
|
2823
|
+
resourceType: "IdP service",
|
|
2824
|
+
resourceName: idp.name
|
|
2825
|
+
});
|
|
2826
|
+
else if (existing.label !== appName) conflicts.push({
|
|
2827
|
+
resourceType: "IdP service",
|
|
2828
|
+
resourceName: idp.name,
|
|
2829
|
+
currentOwner: existing.label
|
|
2830
|
+
});
|
|
2745
2831
|
changeSet.updates.push({
|
|
2746
2832
|
name: namespaceName,
|
|
2747
2833
|
request: {
|
|
2748
2834
|
workspaceId,
|
|
2749
2835
|
namespaceName,
|
|
2750
2836
|
authorization
|
|
2751
|
-
}
|
|
2837
|
+
},
|
|
2838
|
+
metaRequest
|
|
2752
2839
|
});
|
|
2753
|
-
|
|
2840
|
+
delete existingServices[namespaceName];
|
|
2754
2841
|
} else changeSet.creates.push({
|
|
2755
2842
|
name: namespaceName,
|
|
2756
2843
|
request: {
|
|
2757
2844
|
workspaceId,
|
|
2758
2845
|
namespaceName,
|
|
2759
2846
|
authorization
|
|
2760
|
-
}
|
|
2847
|
+
},
|
|
2848
|
+
metaRequest
|
|
2761
2849
|
});
|
|
2762
2850
|
}
|
|
2763
|
-
|
|
2764
|
-
|
|
2851
|
+
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
2852
|
+
const label = existingServices[namespaceName]?.label;
|
|
2853
|
+
if (label && label !== appName) resourceOwners.add(label);
|
|
2854
|
+
if (label === appName) changeSet.deletes.push({
|
|
2765
2855
|
name: namespaceName,
|
|
2766
2856
|
request: {
|
|
2767
2857
|
workspaceId,
|
|
@@ -2769,7 +2859,12 @@ async function planServices$3(client, workspaceId, idps) {
|
|
|
2769
2859
|
}
|
|
2770
2860
|
});
|
|
2771
2861
|
});
|
|
2772
|
-
return
|
|
2862
|
+
return {
|
|
2863
|
+
changeSet,
|
|
2864
|
+
conflicts,
|
|
2865
|
+
unmanaged,
|
|
2866
|
+
resourceOwners
|
|
2867
|
+
};
|
|
2773
2868
|
}
|
|
2774
2869
|
async function planClients(client, workspaceId, idps, deletedServices) {
|
|
2775
2870
|
const changeSet = new ChangeSet("IdP clients");
|
|
@@ -2813,7 +2908,6 @@ async function planClients(client, workspaceId, idps, deletedServices) {
|
|
|
2813
2908
|
});
|
|
2814
2909
|
existingNameMap.forEach((name) => {
|
|
2815
2910
|
changeSet.deletes.push({
|
|
2816
|
-
tag: "client-deleted",
|
|
2817
2911
|
name,
|
|
2818
2912
|
request: {
|
|
2819
2913
|
workspaceId,
|
|
@@ -2825,8 +2919,12 @@ async function planClients(client, workspaceId, idps, deletedServices) {
|
|
|
2825
2919
|
}
|
|
2826
2920
|
for (const namespaceName of deletedServices) (await fetchClients(namespaceName)).forEach((client$1) => {
|
|
2827
2921
|
changeSet.deletes.push({
|
|
2828
|
-
|
|
2829
|
-
|
|
2922
|
+
name: client$1.name,
|
|
2923
|
+
request: {
|
|
2924
|
+
workspaceId,
|
|
2925
|
+
namespaceName,
|
|
2926
|
+
name: client$1.name
|
|
2927
|
+
}
|
|
2830
2928
|
});
|
|
2831
2929
|
});
|
|
2832
2930
|
return changeSet;
|
|
@@ -2834,9 +2932,13 @@ async function planClients(client, workspaceId, idps, deletedServices) {
|
|
|
2834
2932
|
|
|
2835
2933
|
//#endregion
|
|
2836
2934
|
//#region src/cli/apply/services/auth.ts
|
|
2837
|
-
async function applyAuth(client,
|
|
2935
|
+
async function applyAuth(client, result, phase = "create-update") {
|
|
2936
|
+
const { changeSet } = result;
|
|
2838
2937
|
if (phase === "create-update") {
|
|
2839
|
-
await Promise.all(changeSet.service.creates.map((create) =>
|
|
2938
|
+
await Promise.all([...changeSet.service.creates.map(async (create) => {
|
|
2939
|
+
await client.createAuthService(create.request);
|
|
2940
|
+
await client.setMetadata(create.metaRequest);
|
|
2941
|
+
}), ...changeSet.service.updates.map((update) => client.setMetadata(update.metaRequest))]);
|
|
2840
2942
|
await Promise.all([...changeSet.idpConfig.creates.map(async (create) => {
|
|
2841
2943
|
if (create.idpConfig.kind === "BuiltInIdP") create.request.idpConfig.config = await protoBuiltinIdPConfig(client, create.request.workspaceId, create.idpConfig);
|
|
2842
2944
|
return client.createAuthIDPConfig(create.request);
|
|
@@ -2857,23 +2959,23 @@ async function applyAuth(client, changeSet, phase = "create-update") {
|
|
|
2857
2959
|
await Promise.all([...changeSet.scim.creates.map((create) => client.createAuthSCIMConfig(create.request)), ...changeSet.scim.updates.map((update) => client.updateAuthSCIMConfig(update.request))]);
|
|
2858
2960
|
await Promise.all([...changeSet.scimResource.creates.map((create) => client.createAuthSCIMResource(create.request)), ...changeSet.scimResource.updates.map((update) => client.updateAuthSCIMResource(update.request))]);
|
|
2859
2961
|
} else if (phase === "delete") {
|
|
2860
|
-
await Promise.all(changeSet.scimResource.deletes.
|
|
2861
|
-
await Promise.all(changeSet.scim.deletes.
|
|
2862
|
-
await Promise.all(changeSet.oauth2Client.deletes.
|
|
2863
|
-
await Promise.all(changeSet.machineUser.deletes.
|
|
2864
|
-
await Promise.all(changeSet.tenantConfig.deletes.
|
|
2865
|
-
await Promise.all(changeSet.userProfileConfig.deletes.
|
|
2866
|
-
await Promise.all(changeSet.idpConfig.deletes.
|
|
2962
|
+
await Promise.all(changeSet.scimResource.deletes.map((del) => client.deleteAuthSCIMResource(del.request)));
|
|
2963
|
+
await Promise.all(changeSet.scim.deletes.map((del) => client.deleteAuthSCIMConfig(del.request)));
|
|
2964
|
+
await Promise.all(changeSet.oauth2Client.deletes.map((del) => client.deleteAuthOAuth2Client(del.request)));
|
|
2965
|
+
await Promise.all(changeSet.machineUser.deletes.map((del) => client.deleteAuthMachineUser(del.request)));
|
|
2966
|
+
await Promise.all(changeSet.tenantConfig.deletes.map((del) => client.deleteTenantConfig(del.request)));
|
|
2967
|
+
await Promise.all(changeSet.userProfileConfig.deletes.map((del) => client.deleteUserProfileConfig(del.request)));
|
|
2968
|
+
await Promise.all(changeSet.idpConfig.deletes.map((del) => client.deleteAuthIDPConfig(del.request)));
|
|
2867
2969
|
await Promise.all(changeSet.service.deletes.map((del) => client.deleteAuthService(del.request)));
|
|
2868
2970
|
}
|
|
2869
2971
|
}
|
|
2870
|
-
async function planAuth(client, workspaceId, application) {
|
|
2972
|
+
async function planAuth({ client, workspaceId, application }) {
|
|
2871
2973
|
const auths = [];
|
|
2872
|
-
|
|
2873
|
-
await
|
|
2874
|
-
auths.push(
|
|
2974
|
+
if (application.authService) {
|
|
2975
|
+
await application.authService.resolveNamespaces();
|
|
2976
|
+
auths.push(application.authService);
|
|
2875
2977
|
}
|
|
2876
|
-
const serviceChangeSet = await planServices$2(client, workspaceId, auths);
|
|
2978
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$2(client, workspaceId, application.name, auths);
|
|
2877
2979
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
2878
2980
|
const idpConfigChangeSet = await planIdPConfigs(client, workspaceId, auths, deletedServices);
|
|
2879
2981
|
const userProfileConfigChangeSet = await planUserProfileConfigs(client, workspaceId, auths, deletedServices);
|
|
@@ -2891,19 +2993,30 @@ async function planAuth(client, workspaceId, application) {
|
|
|
2891
2993
|
scimChangeSet.print();
|
|
2892
2994
|
scimResourceChangeSet.print();
|
|
2893
2995
|
return {
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2996
|
+
changeSet: {
|
|
2997
|
+
service: serviceChangeSet,
|
|
2998
|
+
idpConfig: idpConfigChangeSet,
|
|
2999
|
+
userProfileConfig: userProfileConfigChangeSet,
|
|
3000
|
+
tenantConfig: tenantConfigChangeSet,
|
|
3001
|
+
machineUser: machineUserChangeSet,
|
|
3002
|
+
oauth2Client: oauth2ClientChangeSet,
|
|
3003
|
+
scim: scimChangeSet,
|
|
3004
|
+
scimResource: scimResourceChangeSet
|
|
3005
|
+
},
|
|
3006
|
+
conflicts,
|
|
3007
|
+
unmanaged,
|
|
3008
|
+
resourceOwners
|
|
2902
3009
|
};
|
|
2903
3010
|
}
|
|
2904
|
-
|
|
3011
|
+
function trn$4(workspaceId, name) {
|
|
3012
|
+
return `trn:v1:workspace:${workspaceId}:auth:${name}`;
|
|
3013
|
+
}
|
|
3014
|
+
async function planServices$2(client, workspaceId, appName, auths) {
|
|
2905
3015
|
const changeSet = new ChangeSet("Auth services");
|
|
2906
|
-
const
|
|
3016
|
+
const conflicts = [];
|
|
3017
|
+
const unmanaged = [];
|
|
3018
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
3019
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
2907
3020
|
try {
|
|
2908
3021
|
const { authServices, nextPageToken } = await client.listAuthServices({
|
|
2909
3022
|
workspaceId,
|
|
@@ -2915,23 +3028,46 @@ async function planServices$2(client, workspaceId, auths) {
|
|
|
2915
3028
|
throw error;
|
|
2916
3029
|
}
|
|
2917
3030
|
});
|
|
2918
|
-
const
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
}
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
3031
|
+
const existingServices = {};
|
|
3032
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
3033
|
+
if (!resource.namespace?.name) return;
|
|
3034
|
+
const { metadata } = await client.getMetadata({ trn: trn$4(workspaceId, resource.namespace.name) });
|
|
3035
|
+
existingServices[resource.namespace.name] = {
|
|
3036
|
+
resource,
|
|
3037
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
3038
|
+
};
|
|
3039
|
+
}));
|
|
3040
|
+
for (const { config } of auths) {
|
|
3041
|
+
const existing = existingServices[config.name];
|
|
3042
|
+
const metaRequest = await buildMetaRequest(trn$4(workspaceId, config.name), appName);
|
|
3043
|
+
if (existing) {
|
|
3044
|
+
if (!existing.label) unmanaged.push({
|
|
3045
|
+
resourceType: "Auth service",
|
|
3046
|
+
resourceName: config.name
|
|
3047
|
+
});
|
|
3048
|
+
else if (existing.label !== appName) conflicts.push({
|
|
3049
|
+
resourceType: "Auth service",
|
|
3050
|
+
resourceName: config.name,
|
|
3051
|
+
currentOwner: existing.label
|
|
3052
|
+
});
|
|
3053
|
+
changeSet.updates.push({
|
|
3054
|
+
name: config.name,
|
|
3055
|
+
metaRequest
|
|
3056
|
+
});
|
|
3057
|
+
delete existingServices[config.name];
|
|
3058
|
+
} else changeSet.creates.push({
|
|
3059
|
+
name: config.name,
|
|
3060
|
+
request: {
|
|
3061
|
+
workspaceId,
|
|
3062
|
+
namespaceName: config.name
|
|
3063
|
+
},
|
|
3064
|
+
metaRequest
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
3067
|
+
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
3068
|
+
const label = existingServices[namespaceName]?.label;
|
|
3069
|
+
if (label && label !== appName) resourceOwners.add(label);
|
|
3070
|
+
if (label === appName) changeSet.deletes.push({
|
|
2935
3071
|
name: namespaceName,
|
|
2936
3072
|
request: {
|
|
2937
3073
|
workspaceId,
|
|
@@ -2939,7 +3075,12 @@ async function planServices$2(client, workspaceId, auths) {
|
|
|
2939
3075
|
}
|
|
2940
3076
|
});
|
|
2941
3077
|
});
|
|
2942
|
-
return
|
|
3078
|
+
return {
|
|
3079
|
+
changeSet,
|
|
3080
|
+
conflicts,
|
|
3081
|
+
unmanaged,
|
|
3082
|
+
resourceOwners
|
|
3083
|
+
};
|
|
2943
3084
|
}
|
|
2944
3085
|
async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
|
|
2945
3086
|
const changeSet = new ChangeSet("Auth idpConfigs");
|
|
@@ -2987,7 +3128,6 @@ async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
2987
3128
|
});
|
|
2988
3129
|
existingNameSet.forEach((name) => {
|
|
2989
3130
|
changeSet.deletes.push({
|
|
2990
|
-
tag: "idp-config-deleted",
|
|
2991
3131
|
name,
|
|
2992
3132
|
request: {
|
|
2993
3133
|
workspaceId,
|
|
@@ -2999,8 +3139,12 @@ async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
2999
3139
|
}
|
|
3000
3140
|
for (const namespaceName of deletedServices) (await fetchIdPConfigs(namespaceName)).forEach((idpConfig) => {
|
|
3001
3141
|
changeSet.deletes.push({
|
|
3002
|
-
|
|
3003
|
-
|
|
3142
|
+
name: idpConfig.name,
|
|
3143
|
+
request: {
|
|
3144
|
+
workspaceId,
|
|
3145
|
+
namespaceName,
|
|
3146
|
+
name: idpConfig.name
|
|
3147
|
+
}
|
|
3004
3148
|
});
|
|
3005
3149
|
});
|
|
3006
3150
|
return changeSet;
|
|
@@ -3126,7 +3270,6 @@ async function planUserProfileConfigs(client, workspaceId, auths, deletedService
|
|
|
3126
3270
|
}
|
|
3127
3271
|
});
|
|
3128
3272
|
else changeSet.deletes.push({
|
|
3129
|
-
tag: "user-profile-config-deleted",
|
|
3130
3273
|
name,
|
|
3131
3274
|
request: {
|
|
3132
3275
|
workspaceId,
|
|
@@ -3145,8 +3288,11 @@ async function planUserProfileConfigs(client, workspaceId, auths, deletedService
|
|
|
3145
3288
|
throw error;
|
|
3146
3289
|
}
|
|
3147
3290
|
changeSet.deletes.push({
|
|
3148
|
-
|
|
3149
|
-
|
|
3291
|
+
name: `${namespaceName}-user-profile-config`,
|
|
3292
|
+
request: {
|
|
3293
|
+
workspaceId,
|
|
3294
|
+
namespaceName
|
|
3295
|
+
}
|
|
3150
3296
|
});
|
|
3151
3297
|
}
|
|
3152
3298
|
return changeSet;
|
|
@@ -3201,7 +3347,6 @@ async function planTenantConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
3201
3347
|
}
|
|
3202
3348
|
});
|
|
3203
3349
|
else changeSet.deletes.push({
|
|
3204
|
-
tag: "tenant-config-deleted",
|
|
3205
3350
|
name,
|
|
3206
3351
|
request: {
|
|
3207
3352
|
workspaceId,
|
|
@@ -3220,8 +3365,11 @@ async function planTenantConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
3220
3365
|
throw error;
|
|
3221
3366
|
}
|
|
3222
3367
|
changeSet.deletes.push({
|
|
3223
|
-
|
|
3224
|
-
|
|
3368
|
+
name: `${namespaceName}-tenant-config`,
|
|
3369
|
+
request: {
|
|
3370
|
+
workspaceId,
|
|
3371
|
+
namespaceName
|
|
3372
|
+
}
|
|
3225
3373
|
});
|
|
3226
3374
|
}
|
|
3227
3375
|
return changeSet;
|
|
@@ -3290,7 +3438,6 @@ async function planMachineUsers(client, workspaceId, auths, deletedServices) {
|
|
|
3290
3438
|
}
|
|
3291
3439
|
existingNameSet.forEach((name) => {
|
|
3292
3440
|
changeSet.deletes.push({
|
|
3293
|
-
tag: "machine-user-deleted",
|
|
3294
3441
|
name,
|
|
3295
3442
|
request: {
|
|
3296
3443
|
workspaceId,
|
|
@@ -3302,8 +3449,12 @@ async function planMachineUsers(client, workspaceId, auths, deletedServices) {
|
|
|
3302
3449
|
}
|
|
3303
3450
|
for (const namespaceName of deletedServices) (await fetchMachineUsers(namespaceName)).forEach((machineUser) => {
|
|
3304
3451
|
changeSet.deletes.push({
|
|
3305
|
-
|
|
3306
|
-
|
|
3452
|
+
name: machineUser.name,
|
|
3453
|
+
request: {
|
|
3454
|
+
workspaceId,
|
|
3455
|
+
authNamespace: namespaceName,
|
|
3456
|
+
name: machineUser.name
|
|
3457
|
+
}
|
|
3307
3458
|
});
|
|
3308
3459
|
});
|
|
3309
3460
|
return changeSet;
|
|
@@ -3360,7 +3511,6 @@ async function planOAuth2Clients(client, workspaceId, auths, deletedServices) {
|
|
|
3360
3511
|
}
|
|
3361
3512
|
existingNameSet.forEach((name) => {
|
|
3362
3513
|
changeSet.deletes.push({
|
|
3363
|
-
tag: "oauth2-client-deleted",
|
|
3364
3514
|
name,
|
|
3365
3515
|
request: {
|
|
3366
3516
|
workspaceId,
|
|
@@ -3372,8 +3522,12 @@ async function planOAuth2Clients(client, workspaceId, auths, deletedServices) {
|
|
|
3372
3522
|
}
|
|
3373
3523
|
for (const namespaceName of deletedServices) (await fetchOAuth2Clients(namespaceName)).forEach((oauth2Client) => {
|
|
3374
3524
|
changeSet.deletes.push({
|
|
3375
|
-
|
|
3376
|
-
|
|
3525
|
+
name: oauth2Client.name,
|
|
3526
|
+
request: {
|
|
3527
|
+
workspaceId,
|
|
3528
|
+
namespaceName,
|
|
3529
|
+
name: oauth2Client.name
|
|
3530
|
+
}
|
|
3377
3531
|
});
|
|
3378
3532
|
});
|
|
3379
3533
|
return changeSet;
|
|
@@ -3429,7 +3583,6 @@ async function planSCIMConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
3429
3583
|
}
|
|
3430
3584
|
});
|
|
3431
3585
|
else changeSet.deletes.push({
|
|
3432
|
-
tag: "scim-config-deleted",
|
|
3433
3586
|
name,
|
|
3434
3587
|
request: {
|
|
3435
3588
|
workspaceId,
|
|
@@ -3448,8 +3601,11 @@ async function planSCIMConfigs(client, workspaceId, auths, deletedServices) {
|
|
|
3448
3601
|
throw error;
|
|
3449
3602
|
}
|
|
3450
3603
|
changeSet.deletes.push({
|
|
3451
|
-
|
|
3452
|
-
|
|
3604
|
+
name: `${namespaceName}-scim-config`,
|
|
3605
|
+
request: {
|
|
3606
|
+
workspaceId,
|
|
3607
|
+
namespaceName
|
|
3608
|
+
}
|
|
3453
3609
|
});
|
|
3454
3610
|
}
|
|
3455
3611
|
return changeSet;
|
|
@@ -3517,7 +3673,6 @@ async function planSCIMResources(client, workspaceId, auths, deletedServices) {
|
|
|
3517
3673
|
});
|
|
3518
3674
|
existingNameSet.forEach((name) => {
|
|
3519
3675
|
changeSet.deletes.push({
|
|
3520
|
-
tag: "scim-resource-deleted",
|
|
3521
3676
|
name,
|
|
3522
3677
|
request: {
|
|
3523
3678
|
workspaceId,
|
|
@@ -3529,8 +3684,12 @@ async function planSCIMResources(client, workspaceId, auths, deletedServices) {
|
|
|
3529
3684
|
}
|
|
3530
3685
|
for (const namespaceName of deletedServices) (await fetchSCIMResources(namespaceName)).forEach((scimResource) => {
|
|
3531
3686
|
changeSet.deletes.push({
|
|
3532
|
-
|
|
3533
|
-
|
|
3687
|
+
name: scimResource.name,
|
|
3688
|
+
request: {
|
|
3689
|
+
workspaceId,
|
|
3690
|
+
namespaceName,
|
|
3691
|
+
name: scimResource.name
|
|
3692
|
+
}
|
|
3534
3693
|
});
|
|
3535
3694
|
});
|
|
3536
3695
|
return changeSet;
|
|
@@ -3609,15 +3768,72 @@ function protoSCIMAttribute(attr) {
|
|
|
3609
3768
|
};
|
|
3610
3769
|
}
|
|
3611
3770
|
|
|
3771
|
+
//#endregion
|
|
3772
|
+
//#region src/cli/apply/services/confirm.ts
|
|
3773
|
+
async function confirmOwnerConflict(conflicts, appName, yes) {
|
|
3774
|
+
if (conflicts.length === 0) return;
|
|
3775
|
+
const currentOwners = [...new Set(conflicts.map((c) => c.currentOwner))];
|
|
3776
|
+
consola.warn("Application name mismatch detected:");
|
|
3777
|
+
console.log(` ${chalk.yellow("Current application(s)")}: ${currentOwners.map((o) => chalk.bold(`"${o}"`)).join(", ")}`);
|
|
3778
|
+
console.log(` ${chalk.green("New application")}: ${chalk.bold(`"${appName}"`)}`);
|
|
3779
|
+
console.log("");
|
|
3780
|
+
console.log(` ${chalk.cyan("Resources")}:`);
|
|
3781
|
+
for (const c of conflicts) console.log(` • ${chalk.bold(c.resourceType)} ${chalk.cyan(`"${c.resourceName}"`)}`);
|
|
3782
|
+
if (yes) {
|
|
3783
|
+
consola.success("Updating resources (--yes flag specified)...");
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
const promptMessage = currentOwners.length === 1 ? `Update these resources to be managed by "${appName}"?\n${chalk.gray("(Common when renaming your application)")}` : `Update these resources to be managed by "${appName}"?`;
|
|
3787
|
+
if (!await consola.prompt(promptMessage, {
|
|
3788
|
+
type: "confirm",
|
|
3789
|
+
initial: false
|
|
3790
|
+
})) throw new Error(ml`
|
|
3791
|
+
Apply cancelled. Resources remain managed by their current applications.
|
|
3792
|
+
To override, run again and confirm, or use --yes flag.
|
|
3793
|
+
`);
|
|
3794
|
+
}
|
|
3795
|
+
async function confirmUnmanagedResources(resources, appName, yes) {
|
|
3796
|
+
if (resources.length === 0) return;
|
|
3797
|
+
consola.warn("Unmanaged resources detected:");
|
|
3798
|
+
console.log(` ${chalk.cyan("Resources")}:`);
|
|
3799
|
+
for (const r of resources) console.log(` • ${chalk.bold(r.resourceType)} ${chalk.cyan(`"${r.resourceName}"`)}`);
|
|
3800
|
+
console.log("");
|
|
3801
|
+
console.log(" These resources are not managed by any application.");
|
|
3802
|
+
if (yes) {
|
|
3803
|
+
consola.success(`Adding to "${appName}" (--yes flag specified)...`);
|
|
3804
|
+
return;
|
|
3805
|
+
}
|
|
3806
|
+
if (!await consola.prompt(`Add these resources to "${appName}"?`, {
|
|
3807
|
+
type: "confirm",
|
|
3808
|
+
initial: false
|
|
3809
|
+
})) throw new Error(ml`
|
|
3810
|
+
Apply cancelled. Resources remain unmanaged.
|
|
3811
|
+
To override, run again and confirm, or use --yes flag.
|
|
3812
|
+
`);
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3612
3815
|
//#endregion
|
|
3613
3816
|
//#region src/cli/apply/services/executor.ts
|
|
3614
|
-
async function applyExecutor(client,
|
|
3615
|
-
|
|
3817
|
+
async function applyExecutor(client, result, phase = "create-update") {
|
|
3818
|
+
const { changeSet } = result;
|
|
3819
|
+
if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
|
|
3820
|
+
await client.createExecutorExecutor(create.request);
|
|
3821
|
+
await client.setMetadata(create.metaRequest);
|
|
3822
|
+
}), ...changeSet.updates.map(async (update) => {
|
|
3823
|
+
await client.updateExecutorExecutor(update.request);
|
|
3824
|
+
await client.setMetadata(update.metaRequest);
|
|
3825
|
+
})]);
|
|
3616
3826
|
else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteExecutorExecutor(del.request)));
|
|
3617
3827
|
}
|
|
3618
|
-
|
|
3828
|
+
function trn$3(workspaceId, name) {
|
|
3829
|
+
return `trn:v1:workspace:${workspaceId}:executor:${name}`;
|
|
3830
|
+
}
|
|
3831
|
+
async function planExecutor({ client, workspaceId, application }) {
|
|
3619
3832
|
const changeSet = new ChangeSet("Executors");
|
|
3620
|
-
const
|
|
3833
|
+
const conflicts = [];
|
|
3834
|
+
const unmanaged = [];
|
|
3835
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
3836
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
3621
3837
|
try {
|
|
3622
3838
|
const { executors: executors$1, nextPageToken } = await client.listExecutorExecutors({
|
|
3623
3839
|
workspaceId,
|
|
@@ -3629,29 +3845,50 @@ async function planExecutor(client, workspaceId, application) {
|
|
|
3629
3845
|
throw error;
|
|
3630
3846
|
}
|
|
3631
3847
|
});
|
|
3632
|
-
const
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3848
|
+
const existingExecutors = {};
|
|
3849
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
3850
|
+
const { metadata } = await client.getMetadata({ trn: trn$3(workspaceId, resource.name) });
|
|
3851
|
+
existingExecutors[resource.name] = {
|
|
3852
|
+
resource,
|
|
3853
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
3854
|
+
};
|
|
3855
|
+
}));
|
|
3636
3856
|
const executors = await application.executorService?.loadExecutors() ?? {};
|
|
3637
|
-
for (const executor of Object.values(executors))
|
|
3638
|
-
|
|
3857
|
+
for (const executor of Object.values(executors)) {
|
|
3858
|
+
const existing = existingExecutors[executor.name];
|
|
3859
|
+
const metaRequest = await buildMetaRequest(trn$3(workspaceId, executor.name), application.name);
|
|
3860
|
+
if (existing) {
|
|
3861
|
+
if (!existing.label) unmanaged.push({
|
|
3862
|
+
resourceType: "Executor",
|
|
3863
|
+
resourceName: executor.name
|
|
3864
|
+
});
|
|
3865
|
+
else if (existing.label !== application.name) conflicts.push({
|
|
3866
|
+
resourceType: "Executor",
|
|
3867
|
+
resourceName: executor.name,
|
|
3868
|
+
currentOwner: existing.label
|
|
3869
|
+
});
|
|
3870
|
+
changeSet.updates.push({
|
|
3871
|
+
name: executor.name,
|
|
3872
|
+
request: {
|
|
3873
|
+
workspaceId,
|
|
3874
|
+
executor: protoExecutor(executor)
|
|
3875
|
+
},
|
|
3876
|
+
metaRequest
|
|
3877
|
+
});
|
|
3878
|
+
delete existingExecutors[executor.name];
|
|
3879
|
+
} else changeSet.creates.push({
|
|
3639
3880
|
name: executor.name,
|
|
3640
3881
|
request: {
|
|
3641
3882
|
workspaceId,
|
|
3642
3883
|
executor: protoExecutor(executor)
|
|
3643
|
-
}
|
|
3884
|
+
},
|
|
3885
|
+
metaRequest
|
|
3644
3886
|
});
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
executor: protoExecutor(executor)
|
|
3651
|
-
}
|
|
3652
|
-
});
|
|
3653
|
-
existingNameSet.forEach((name) => {
|
|
3654
|
-
changeSet.deletes.push({
|
|
3887
|
+
}
|
|
3888
|
+
Object.entries(existingExecutors).forEach(([name]) => {
|
|
3889
|
+
const label = existingExecutors[name]?.label;
|
|
3890
|
+
if (label && label !== application.name) resourceOwners.add(label);
|
|
3891
|
+
if (label === application.name) changeSet.deletes.push({
|
|
3655
3892
|
name,
|
|
3656
3893
|
request: {
|
|
3657
3894
|
workspaceId,
|
|
@@ -3660,7 +3897,12 @@ async function planExecutor(client, workspaceId, application) {
|
|
|
3660
3897
|
});
|
|
3661
3898
|
});
|
|
3662
3899
|
changeSet.print();
|
|
3663
|
-
return
|
|
3900
|
+
return {
|
|
3901
|
+
changeSet,
|
|
3902
|
+
conflicts,
|
|
3903
|
+
unmanaged,
|
|
3904
|
+
resourceOwners
|
|
3905
|
+
};
|
|
3664
3906
|
}
|
|
3665
3907
|
function protoExecutor(executor) {
|
|
3666
3908
|
const trigger = executor.trigger;
|
|
@@ -3830,35 +4072,53 @@ const SCALAR_TYPE_MAP = {
|
|
|
3830
4072
|
name: "Time"
|
|
3831
4073
|
}
|
|
3832
4074
|
};
|
|
3833
|
-
async function applyPipeline(client,
|
|
4075
|
+
async function applyPipeline(client, result, phase = "create-update") {
|
|
4076
|
+
const { changeSet } = result;
|
|
3834
4077
|
if (phase === "create-update") {
|
|
3835
|
-
await Promise.all([...changeSet.service.creates.map(
|
|
4078
|
+
await Promise.all([...changeSet.service.creates.map(async (create) => {
|
|
4079
|
+
await client.createPipelineService(create.request);
|
|
4080
|
+
await client.setMetadata(create.metaRequest);
|
|
4081
|
+
}), ...changeSet.service.updates.map(async (update) => {
|
|
4082
|
+
await client.updatePipelineService(update.request);
|
|
4083
|
+
await client.setMetadata(update.metaRequest);
|
|
4084
|
+
})]);
|
|
3836
4085
|
await Promise.all([...changeSet.resolver.creates.map((create) => client.createPipelineResolver(create.request)), ...changeSet.resolver.updates.map((update) => client.updatePipelineResolver(update.request))]);
|
|
3837
4086
|
} else if (phase === "delete") {
|
|
3838
|
-
await Promise.all(changeSet.resolver.deletes.
|
|
4087
|
+
await Promise.all(changeSet.resolver.deletes.map((del) => client.deletePipelineResolver(del.request)));
|
|
3839
4088
|
await Promise.all(changeSet.service.deletes.map((del) => client.deletePipelineService(del.request)));
|
|
3840
4089
|
}
|
|
3841
4090
|
}
|
|
3842
|
-
async function planPipeline(client, workspaceId, application) {
|
|
4091
|
+
async function planPipeline({ client, workspaceId, application }) {
|
|
3843
4092
|
const pipelines = [];
|
|
3844
|
-
for (const
|
|
4093
|
+
for (const pipeline of application.resolverServices) {
|
|
3845
4094
|
await pipeline.loadResolvers();
|
|
3846
4095
|
pipelines.push(pipeline);
|
|
3847
4096
|
}
|
|
3848
4097
|
const executors = Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
3849
|
-
const serviceChangeSet = await planServices$1(client, workspaceId, pipelines);
|
|
4098
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$1(client, workspaceId, application.name, pipelines);
|
|
3850
4099
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
3851
4100
|
const resolverChangeSet = await planResolvers(client, workspaceId, pipelines, executors, deletedServices);
|
|
3852
4101
|
serviceChangeSet.print();
|
|
3853
4102
|
resolverChangeSet.print();
|
|
3854
4103
|
return {
|
|
3855
|
-
|
|
3856
|
-
|
|
4104
|
+
changeSet: {
|
|
4105
|
+
service: serviceChangeSet,
|
|
4106
|
+
resolver: resolverChangeSet
|
|
4107
|
+
},
|
|
4108
|
+
conflicts,
|
|
4109
|
+
unmanaged,
|
|
4110
|
+
resourceOwners
|
|
3857
4111
|
};
|
|
3858
4112
|
}
|
|
3859
|
-
|
|
4113
|
+
function trn$2(workspaceId, name) {
|
|
4114
|
+
return `trn:v1:workspace:${workspaceId}:pipeline:${name}`;
|
|
4115
|
+
}
|
|
4116
|
+
async function planServices$1(client, workspaceId, appName, pipelines) {
|
|
3860
4117
|
const changeSet = new ChangeSet("Pipeline services");
|
|
3861
|
-
const
|
|
4118
|
+
const conflicts = [];
|
|
4119
|
+
const unmanaged = [];
|
|
4120
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
4121
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
3862
4122
|
try {
|
|
3863
4123
|
const { pipelineServices, nextPageToken } = await client.listPipelineServices({
|
|
3864
4124
|
workspaceId,
|
|
@@ -3870,29 +4130,50 @@ async function planServices$1(client, workspaceId, pipelines) {
|
|
|
3870
4130
|
throw error;
|
|
3871
4131
|
}
|
|
3872
4132
|
});
|
|
3873
|
-
const
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
4133
|
+
const existingServices = {};
|
|
4134
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
4135
|
+
if (!resource.namespace?.name) return;
|
|
4136
|
+
const { metadata } = await client.getMetadata({ trn: trn$2(workspaceId, resource.namespace.name) });
|
|
4137
|
+
existingServices[resource.namespace.name] = {
|
|
4138
|
+
resource,
|
|
4139
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
4140
|
+
};
|
|
4141
|
+
}));
|
|
4142
|
+
for (const pipeline of pipelines) {
|
|
4143
|
+
const existing = existingServices[pipeline.namespace];
|
|
4144
|
+
const metaRequest = await buildMetaRequest(trn$2(workspaceId, pipeline.namespace), appName);
|
|
4145
|
+
if (existing) {
|
|
4146
|
+
if (!existing.label) unmanaged.push({
|
|
4147
|
+
resourceType: "Pipeline service",
|
|
4148
|
+
resourceName: pipeline.namespace
|
|
4149
|
+
});
|
|
4150
|
+
else if (existing.label !== appName) conflicts.push({
|
|
4151
|
+
resourceType: "Pipeline service",
|
|
4152
|
+
resourceName: pipeline.namespace,
|
|
4153
|
+
currentOwner: existing.label
|
|
4154
|
+
});
|
|
4155
|
+
changeSet.updates.push({
|
|
4156
|
+
name: pipeline.namespace,
|
|
4157
|
+
request: {
|
|
4158
|
+
workspaceId,
|
|
4159
|
+
namespaceName: pipeline.namespace
|
|
4160
|
+
},
|
|
4161
|
+
metaRequest
|
|
4162
|
+
});
|
|
4163
|
+
delete existingServices[pipeline.namespace];
|
|
4164
|
+
} else changeSet.creates.push({
|
|
3880
4165
|
name: pipeline.namespace,
|
|
3881
4166
|
request: {
|
|
3882
4167
|
workspaceId,
|
|
3883
4168
|
namespaceName: pipeline.namespace
|
|
3884
|
-
}
|
|
4169
|
+
},
|
|
4170
|
+
metaRequest
|
|
3885
4171
|
});
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
namespaceName: pipeline.namespace
|
|
3892
|
-
}
|
|
3893
|
-
});
|
|
3894
|
-
existingNameSet.forEach((namespaceName) => {
|
|
3895
|
-
changeSet.deletes.push({
|
|
4172
|
+
}
|
|
4173
|
+
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
4174
|
+
const label = existingServices[namespaceName]?.label;
|
|
4175
|
+
if (label && label !== appName) resourceOwners.add(label);
|
|
4176
|
+
if (label === appName) changeSet.deletes.push({
|
|
3896
4177
|
name: namespaceName,
|
|
3897
4178
|
request: {
|
|
3898
4179
|
workspaceId,
|
|
@@ -3900,7 +4181,12 @@ async function planServices$1(client, workspaceId, pipelines) {
|
|
|
3900
4181
|
}
|
|
3901
4182
|
});
|
|
3902
4183
|
});
|
|
3903
|
-
return
|
|
4184
|
+
return {
|
|
4185
|
+
changeSet,
|
|
4186
|
+
conflicts,
|
|
4187
|
+
unmanaged,
|
|
4188
|
+
resourceOwners
|
|
4189
|
+
};
|
|
3904
4190
|
}
|
|
3905
4191
|
async function planResolvers(client, workspaceId, pipelines, executors, deletedServices) {
|
|
3906
4192
|
const changeSet = new ChangeSet("Pipeline resolvers");
|
|
@@ -3947,7 +4233,6 @@ async function planResolvers(client, workspaceId, pipelines, executors, deletedS
|
|
|
3947
4233
|
});
|
|
3948
4234
|
existingNameSet.forEach((name) => {
|
|
3949
4235
|
changeSet.deletes.push({
|
|
3950
|
-
tag: "resolver-deleted",
|
|
3951
4236
|
name,
|
|
3952
4237
|
request: {
|
|
3953
4238
|
workspaceId,
|
|
@@ -3959,8 +4244,12 @@ async function planResolvers(client, workspaceId, pipelines, executors, deletedS
|
|
|
3959
4244
|
}
|
|
3960
4245
|
for (const namespaceName of deletedServices) (await fetchResolvers(namespaceName)).forEach((resolver) => {
|
|
3961
4246
|
changeSet.deletes.push({
|
|
3962
|
-
|
|
3963
|
-
|
|
4247
|
+
name: resolver.name,
|
|
4248
|
+
request: {
|
|
4249
|
+
workspaceId,
|
|
4250
|
+
namespaceName,
|
|
4251
|
+
resolverName: resolver.name
|
|
4252
|
+
}
|
|
3964
4253
|
});
|
|
3965
4254
|
});
|
|
3966
4255
|
return changeSet;
|
|
@@ -4034,13 +4323,26 @@ function protoFields(fields, baseName, isInput) {
|
|
|
4034
4323
|
|
|
4035
4324
|
//#endregion
|
|
4036
4325
|
//#region src/cli/apply/services/staticwebsite.ts
|
|
4037
|
-
async function applyStaticWebsite(client,
|
|
4038
|
-
|
|
4326
|
+
async function applyStaticWebsite(client, result, phase = "create-update") {
|
|
4327
|
+
const { changeSet } = result;
|
|
4328
|
+
if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
|
|
4329
|
+
await client.createStaticWebsite(create.request);
|
|
4330
|
+
await client.setMetadata(create.metaRequest);
|
|
4331
|
+
}), ...changeSet.updates.map(async (update) => {
|
|
4332
|
+
await client.updateStaticWebsite(update.request);
|
|
4333
|
+
await client.setMetadata(update.metaRequest);
|
|
4334
|
+
})]);
|
|
4039
4335
|
else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteStaticWebsite(del.request)));
|
|
4040
4336
|
}
|
|
4041
|
-
|
|
4337
|
+
function trn$1(workspaceId, name) {
|
|
4338
|
+
return `trn:v1:workspace:${workspaceId}:staticwebsite:${name}`;
|
|
4339
|
+
}
|
|
4340
|
+
async function planStaticWebsite({ client, workspaceId, application }) {
|
|
4042
4341
|
const changeSet = new ChangeSet("StaticWebsites");
|
|
4043
|
-
const
|
|
4342
|
+
const conflicts = [];
|
|
4343
|
+
const unmanaged = [];
|
|
4344
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
4345
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
4044
4346
|
try {
|
|
4045
4347
|
const { staticwebsites, nextPageToken } = await client.listStaticWebsites({
|
|
4046
4348
|
workspaceId,
|
|
@@ -4052,14 +4354,29 @@ async function planStaticWebsite(client, workspaceId, application) {
|
|
|
4052
4354
|
throw error;
|
|
4053
4355
|
}
|
|
4054
4356
|
});
|
|
4055
|
-
const
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4357
|
+
const existingWebsites = {};
|
|
4358
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
4359
|
+
const { metadata } = await client.getMetadata({ trn: trn$1(workspaceId, resource.name) });
|
|
4360
|
+
existingWebsites[resource.name] = {
|
|
4361
|
+
resource,
|
|
4362
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
4363
|
+
};
|
|
4364
|
+
}));
|
|
4059
4365
|
for (const websiteService of application.staticWebsiteServices) {
|
|
4060
4366
|
const config = websiteService;
|
|
4061
4367
|
const name = websiteService.name;
|
|
4062
|
-
|
|
4368
|
+
const existing = existingWebsites[name];
|
|
4369
|
+
const metaRequest = await buildMetaRequest(trn$1(workspaceId, name), application.name);
|
|
4370
|
+
if (existing) {
|
|
4371
|
+
if (!existing.label) unmanaged.push({
|
|
4372
|
+
resourceType: "StaticWebsite",
|
|
4373
|
+
resourceName: name
|
|
4374
|
+
});
|
|
4375
|
+
else if (existing.label !== application.name) conflicts.push({
|
|
4376
|
+
resourceType: "StaticWebsite",
|
|
4377
|
+
resourceName: name,
|
|
4378
|
+
currentOwner: existing.label
|
|
4379
|
+
});
|
|
4063
4380
|
changeSet.updates.push({
|
|
4064
4381
|
name,
|
|
4065
4382
|
request: {
|
|
@@ -4069,9 +4386,10 @@ async function planStaticWebsite(client, workspaceId, application) {
|
|
|
4069
4386
|
description: config.description || "",
|
|
4070
4387
|
allowedIpAddresses: config.allowedIpAddresses || []
|
|
4071
4388
|
}
|
|
4072
|
-
}
|
|
4389
|
+
},
|
|
4390
|
+
metaRequest
|
|
4073
4391
|
});
|
|
4074
|
-
|
|
4392
|
+
delete existingWebsites[name];
|
|
4075
4393
|
} else changeSet.creates.push({
|
|
4076
4394
|
name,
|
|
4077
4395
|
request: {
|
|
@@ -4081,11 +4399,14 @@ async function planStaticWebsite(client, workspaceId, application) {
|
|
|
4081
4399
|
description: config.description || "",
|
|
4082
4400
|
allowedIpAddresses: config.allowedIpAddresses || []
|
|
4083
4401
|
}
|
|
4084
|
-
}
|
|
4402
|
+
},
|
|
4403
|
+
metaRequest
|
|
4085
4404
|
});
|
|
4086
4405
|
}
|
|
4087
|
-
|
|
4088
|
-
|
|
4406
|
+
Object.entries(existingWebsites).forEach(([name]) => {
|
|
4407
|
+
const label = existingWebsites[name]?.label;
|
|
4408
|
+
if (label && label !== application.name) resourceOwners.add(label);
|
|
4409
|
+
if (label === application.name) changeSet.deletes.push({
|
|
4089
4410
|
name,
|
|
4090
4411
|
request: {
|
|
4091
4412
|
workspaceId,
|
|
@@ -4094,30 +4415,39 @@ async function planStaticWebsite(client, workspaceId, application) {
|
|
|
4094
4415
|
});
|
|
4095
4416
|
});
|
|
4096
4417
|
changeSet.print();
|
|
4097
|
-
return
|
|
4418
|
+
return {
|
|
4419
|
+
changeSet,
|
|
4420
|
+
conflicts,
|
|
4421
|
+
unmanaged,
|
|
4422
|
+
resourceOwners
|
|
4423
|
+
};
|
|
4098
4424
|
}
|
|
4099
4425
|
|
|
4100
4426
|
//#endregion
|
|
4101
4427
|
//#region src/cli/apply/services/tailordb.ts
|
|
4102
|
-
async function applyTailorDB(client,
|
|
4428
|
+
async function applyTailorDB(client, result, phase = "create-update") {
|
|
4429
|
+
const { changeSet } = result;
|
|
4103
4430
|
if (phase === "create-update") {
|
|
4104
|
-
await Promise.all(changeSet.service.creates.map((create) =>
|
|
4431
|
+
await Promise.all([...changeSet.service.creates.map(async (create) => {
|
|
4432
|
+
await client.createTailorDBService(create.request);
|
|
4433
|
+
await client.setMetadata(create.metaRequest);
|
|
4434
|
+
}), ...changeSet.service.updates.map((update) => client.setMetadata(update.metaRequest))]);
|
|
4105
4435
|
await Promise.all([...changeSet.type.creates.map((create) => client.createTailorDBType(create.request)), ...changeSet.type.updates.map((update) => client.updateTailorDBType(update.request))]);
|
|
4106
4436
|
await Promise.all([...changeSet.gqlPermission.creates.map((create) => client.createTailorDBGQLPermission(create.request)), ...changeSet.gqlPermission.updates.map((update) => client.updateTailorDBGQLPermission(update.request))]);
|
|
4107
4437
|
} else if (phase === "delete") {
|
|
4108
|
-
await Promise.all(changeSet.gqlPermission.deletes.
|
|
4109
|
-
await Promise.all(changeSet.type.deletes.
|
|
4438
|
+
await Promise.all(changeSet.gqlPermission.deletes.map((del) => client.deleteTailorDBGQLPermission(del.request)));
|
|
4439
|
+
await Promise.all(changeSet.type.deletes.map((del) => client.deleteTailorDBType(del.request)));
|
|
4110
4440
|
await Promise.all(changeSet.service.deletes.map((del) => client.deleteTailorDBService(del.request)));
|
|
4111
4441
|
}
|
|
4112
4442
|
}
|
|
4113
|
-
async function planTailorDB(client, workspaceId, application) {
|
|
4443
|
+
async function planTailorDB({ client, workspaceId, application }) {
|
|
4114
4444
|
const tailordbs = [];
|
|
4115
|
-
for (const
|
|
4445
|
+
for (const tailordb of application.tailorDBServices) {
|
|
4116
4446
|
await tailordb.loadTypes();
|
|
4117
4447
|
tailordbs.push(tailordb);
|
|
4118
4448
|
}
|
|
4119
4449
|
const executors = Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
4120
|
-
const serviceChangeSet = await planServices(client, workspaceId, tailordbs);
|
|
4450
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, tailordbs);
|
|
4121
4451
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
4122
4452
|
const typeChangeSet = await planTypes(client, workspaceId, tailordbs, executors, deletedServices);
|
|
4123
4453
|
const gqlPermissionChangeSet = await planGqlPermissions(client, workspaceId, tailordbs, deletedServices);
|
|
@@ -4125,14 +4455,25 @@ async function planTailorDB(client, workspaceId, application) {
|
|
|
4125
4455
|
typeChangeSet.print();
|
|
4126
4456
|
gqlPermissionChangeSet.print();
|
|
4127
4457
|
return {
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4458
|
+
changeSet: {
|
|
4459
|
+
service: serviceChangeSet,
|
|
4460
|
+
type: typeChangeSet,
|
|
4461
|
+
gqlPermission: gqlPermissionChangeSet
|
|
4462
|
+
},
|
|
4463
|
+
conflicts,
|
|
4464
|
+
unmanaged,
|
|
4465
|
+
resourceOwners
|
|
4131
4466
|
};
|
|
4132
4467
|
}
|
|
4133
|
-
|
|
4468
|
+
function trn(workspaceId, name) {
|
|
4469
|
+
return `${trnPrefix(workspaceId)}:tailordb:${name}`;
|
|
4470
|
+
}
|
|
4471
|
+
async function planServices(client, workspaceId, appName, tailordbs) {
|
|
4134
4472
|
const changeSet = new ChangeSet("TailorDB services");
|
|
4135
|
-
const
|
|
4473
|
+
const conflicts = [];
|
|
4474
|
+
const unmanaged = [];
|
|
4475
|
+
const resourceOwners = /* @__PURE__ */ new Set();
|
|
4476
|
+
const withoutLabel = await fetchAll(async (pageToken) => {
|
|
4136
4477
|
try {
|
|
4137
4478
|
const { tailordbServices, nextPageToken } = await client.listTailorDBServices({
|
|
4138
4479
|
workspaceId,
|
|
@@ -4144,24 +4485,47 @@ async function planServices(client, workspaceId, tailordbs) {
|
|
|
4144
4485
|
throw error;
|
|
4145
4486
|
}
|
|
4146
4487
|
});
|
|
4147
|
-
const
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
}
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4488
|
+
const existingServices = {};
|
|
4489
|
+
await Promise.all(withoutLabel.map(async (resource) => {
|
|
4490
|
+
if (!resource.namespace?.name) return;
|
|
4491
|
+
const { metadata } = await client.getMetadata({ trn: trn(workspaceId, resource.namespace.name) });
|
|
4492
|
+
existingServices[resource.namespace.name] = {
|
|
4493
|
+
resource,
|
|
4494
|
+
label: metadata?.labels[sdkNameLabelKey]
|
|
4495
|
+
};
|
|
4496
|
+
}));
|
|
4497
|
+
for (const tailordb of tailordbs) {
|
|
4498
|
+
const existing = existingServices[tailordb.namespace];
|
|
4499
|
+
const metaRequest = await buildMetaRequest(trn(workspaceId, tailordb.namespace), appName);
|
|
4500
|
+
if (existing) {
|
|
4501
|
+
if (!existing.label) unmanaged.push({
|
|
4502
|
+
resourceType: "TailorDB service",
|
|
4503
|
+
resourceName: tailordb.namespace
|
|
4504
|
+
});
|
|
4505
|
+
else if (existing.label !== appName) conflicts.push({
|
|
4506
|
+
resourceType: "TailorDB service",
|
|
4507
|
+
resourceName: tailordb.namespace,
|
|
4508
|
+
currentOwner: existing.label
|
|
4509
|
+
});
|
|
4510
|
+
changeSet.updates.push({
|
|
4511
|
+
name: tailordb.namespace,
|
|
4512
|
+
metaRequest
|
|
4513
|
+
});
|
|
4514
|
+
delete existingServices[tailordb.namespace];
|
|
4515
|
+
} else changeSet.creates.push({
|
|
4516
|
+
name: tailordb.namespace,
|
|
4517
|
+
request: {
|
|
4518
|
+
workspaceId,
|
|
4519
|
+
namespaceName: tailordb.namespace,
|
|
4520
|
+
defaultTimezone: "UTC"
|
|
4521
|
+
},
|
|
4522
|
+
metaRequest
|
|
4523
|
+
});
|
|
4524
|
+
}
|
|
4525
|
+
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
4526
|
+
const label = existingServices[namespaceName]?.label;
|
|
4527
|
+
if (label && label !== appName) resourceOwners.add(label);
|
|
4528
|
+
if (label === appName) changeSet.deletes.push({
|
|
4165
4529
|
name: namespaceName,
|
|
4166
4530
|
request: {
|
|
4167
4531
|
workspaceId,
|
|
@@ -4169,7 +4533,12 @@ async function planServices(client, workspaceId, tailordbs) {
|
|
|
4169
4533
|
}
|
|
4170
4534
|
});
|
|
4171
4535
|
});
|
|
4172
|
-
return
|
|
4536
|
+
return {
|
|
4537
|
+
changeSet,
|
|
4538
|
+
conflicts,
|
|
4539
|
+
unmanaged,
|
|
4540
|
+
resourceOwners
|
|
4541
|
+
};
|
|
4173
4542
|
}
|
|
4174
4543
|
async function planTypes(client, workspaceId, tailordbs, executors, deletedServices) {
|
|
4175
4544
|
const changeSet = new ChangeSet("TailorDB types");
|
|
@@ -4218,7 +4587,6 @@ async function planTypes(client, workspaceId, tailordbs, executors, deletedServi
|
|
|
4218
4587
|
}
|
|
4219
4588
|
existingNameSet.forEach((name) => {
|
|
4220
4589
|
changeSet.deletes.push({
|
|
4221
|
-
tag: "type-deleted",
|
|
4222
4590
|
name,
|
|
4223
4591
|
request: {
|
|
4224
4592
|
workspaceId,
|
|
@@ -4230,8 +4598,12 @@ async function planTypes(client, workspaceId, tailordbs, executors, deletedServi
|
|
|
4230
4598
|
}
|
|
4231
4599
|
for (const namespaceName of deletedServices) (await fetchTypes(namespaceName)).forEach((typ) => {
|
|
4232
4600
|
changeSet.deletes.push({
|
|
4233
|
-
|
|
4234
|
-
|
|
4601
|
+
name: typ.name,
|
|
4602
|
+
request: {
|
|
4603
|
+
workspaceId,
|
|
4604
|
+
namespaceName,
|
|
4605
|
+
tailordbTypeName: typ.name
|
|
4606
|
+
}
|
|
4235
4607
|
});
|
|
4236
4608
|
});
|
|
4237
4609
|
return changeSet;
|
|
@@ -4489,7 +4861,6 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
|
|
|
4489
4861
|
}
|
|
4490
4862
|
existingNameSet.forEach((name) => {
|
|
4491
4863
|
changeSet.deletes.push({
|
|
4492
|
-
tag: "gql-permission-deleted",
|
|
4493
4864
|
name,
|
|
4494
4865
|
request: {
|
|
4495
4866
|
workspaceId,
|
|
@@ -4501,8 +4872,12 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
|
|
|
4501
4872
|
}
|
|
4502
4873
|
for (const namespaceName of deletedServices) (await fetchGqlPermissions(namespaceName)).forEach((gqlPermission) => {
|
|
4503
4874
|
changeSet.deletes.push({
|
|
4504
|
-
|
|
4505
|
-
|
|
4875
|
+
name: gqlPermission.typeName,
|
|
4876
|
+
request: {
|
|
4877
|
+
workspaceId,
|
|
4878
|
+
namespaceName,
|
|
4879
|
+
typeName: gqlPermission.typeName
|
|
4880
|
+
}
|
|
4506
4881
|
});
|
|
4507
4882
|
});
|
|
4508
4883
|
return changeSet;
|
|
@@ -4597,6 +4972,7 @@ async function apply(options) {
|
|
|
4597
4972
|
const configPath = loadConfigPath(options?.configPath);
|
|
4598
4973
|
const { config } = await loadConfig(configPath);
|
|
4599
4974
|
const dryRun = options?.dryRun ?? false;
|
|
4975
|
+
const yes = options?.yes ?? false;
|
|
4600
4976
|
const buildOnly = options?.buildOnly ?? false;
|
|
4601
4977
|
await generateUserTypes(config, configPath);
|
|
4602
4978
|
const application = defineApplication(config);
|
|
@@ -4612,13 +4988,56 @@ async function apply(options) {
|
|
|
4612
4988
|
workspaceId: options?.workspaceId,
|
|
4613
4989
|
profile: options?.profile
|
|
4614
4990
|
});
|
|
4615
|
-
const
|
|
4616
|
-
const
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
const
|
|
4620
|
-
|
|
4621
|
-
|
|
4991
|
+
for (const tailordb of application.tailorDBServices) await tailordb.loadTypes();
|
|
4992
|
+
for (const pipeline$1 of application.resolverServices) await pipeline$1.loadResolvers();
|
|
4993
|
+
if (application.executorService) await application.executorService.loadExecutors();
|
|
4994
|
+
console.log("");
|
|
4995
|
+
const ctx = {
|
|
4996
|
+
client,
|
|
4997
|
+
workspaceId,
|
|
4998
|
+
application
|
|
4999
|
+
};
|
|
5000
|
+
const tailorDB = await planTailorDB(ctx);
|
|
5001
|
+
const staticWebsite = await planStaticWebsite(ctx);
|
|
5002
|
+
const idp = await planIdP(ctx);
|
|
5003
|
+
const auth = await planAuth(ctx);
|
|
5004
|
+
const pipeline = await planPipeline(ctx);
|
|
5005
|
+
const app = await planApplication(ctx);
|
|
5006
|
+
const executor = await planExecutor(ctx);
|
|
5007
|
+
const allConflicts = [
|
|
5008
|
+
...tailorDB.conflicts,
|
|
5009
|
+
...staticWebsite.conflicts,
|
|
5010
|
+
...idp.conflicts,
|
|
5011
|
+
...auth.conflicts,
|
|
5012
|
+
...pipeline.conflicts,
|
|
5013
|
+
...executor.conflicts
|
|
5014
|
+
];
|
|
5015
|
+
const allUnmanaged = [
|
|
5016
|
+
...tailorDB.unmanaged,
|
|
5017
|
+
...staticWebsite.unmanaged,
|
|
5018
|
+
...idp.unmanaged,
|
|
5019
|
+
...auth.unmanaged,
|
|
5020
|
+
...pipeline.unmanaged,
|
|
5021
|
+
...executor.unmanaged
|
|
5022
|
+
];
|
|
5023
|
+
await confirmOwnerConflict(allConflicts, application.name, yes);
|
|
5024
|
+
await confirmUnmanagedResources(allUnmanaged, application.name, yes);
|
|
5025
|
+
const resourceOwners = new Set([
|
|
5026
|
+
...tailorDB.resourceOwners,
|
|
5027
|
+
...staticWebsite.resourceOwners,
|
|
5028
|
+
...idp.resourceOwners,
|
|
5029
|
+
...auth.resourceOwners,
|
|
5030
|
+
...pipeline.resourceOwners,
|
|
5031
|
+
...executor.resourceOwners
|
|
5032
|
+
]);
|
|
5033
|
+
const emptyApps = [...new Set(allConflicts.map((c) => c.currentOwner))].filter((owner) => !resourceOwners.has(owner));
|
|
5034
|
+
for (const emptyApp of emptyApps) app.deletes.push({
|
|
5035
|
+
name: emptyApp,
|
|
5036
|
+
request: {
|
|
5037
|
+
workspaceId,
|
|
5038
|
+
applicationName: emptyApp
|
|
5039
|
+
}
|
|
5040
|
+
});
|
|
4622
5041
|
if (dryRun) {
|
|
4623
5042
|
console.log("Dry run enabled. No changes applied.");
|
|
4624
5043
|
return;
|
|
@@ -4693,6 +5112,11 @@ const applyCommand = defineCommand({
|
|
|
4693
5112
|
type: "boolean",
|
|
4694
5113
|
description: "Run the command without making any changes",
|
|
4695
5114
|
alias: "d"
|
|
5115
|
+
},
|
|
5116
|
+
yes: {
|
|
5117
|
+
type: "boolean",
|
|
5118
|
+
description: "Skip all confirmation prompts",
|
|
5119
|
+
alias: "y"
|
|
4696
5120
|
}
|
|
4697
5121
|
},
|
|
4698
5122
|
run: withCommonArgs(async (args) => {
|
|
@@ -4700,7 +5124,8 @@ const applyCommand = defineCommand({
|
|
|
4700
5124
|
workspaceId: args["workspace-id"],
|
|
4701
5125
|
profile: args.profile,
|
|
4702
5126
|
configPath: args.config,
|
|
4703
|
-
dryRun: args.dryRun
|
|
5127
|
+
dryRun: args.dryRun,
|
|
5128
|
+
yes: args.yes
|
|
4704
5129
|
});
|
|
4705
5130
|
})
|
|
4706
5131
|
});
|
|
@@ -5824,4 +6249,4 @@ const tokenCommand = defineCommand({
|
|
|
5824
6249
|
});
|
|
5825
6250
|
|
|
5826
6251
|
//#endregion
|
|
5827
|
-
export { PATScope, apply, applyCommand, commonArgs, createCommand, deleteCommand, fetchAll, fetchLatestToken, formatArgs, generate, generateCommand, generateUserTypes, initOperatorClient, listCommand, listCommand$1, loadAccessToken, loadConfig, loadConfigPath, loadWorkspaceId, machineUserList, machineUserToken, parseFormat, printWithFormat, readPlatformConfig, show, showCommand, tokenCommand, userAgent, withCommonArgs, workspaceCreate, workspaceDelete, workspaceList, writePlatformConfig };
|
|
6252
|
+
export { PATScope, apply, applyCommand, commonArgs, createCommand, deleteCommand, fetchAll, fetchLatestToken, formatArgs, generate, generateCommand, generateUserTypes, initOperatorClient, listCommand, listCommand$1, loadAccessToken, loadConfig, loadConfigPath, loadWorkspaceId, machineUserList, machineUserToken, parseFormat, printWithFormat, readPackageJson, readPlatformConfig, show, showCommand, tokenCommand, userAgent, withCommonArgs, workspaceCreate, workspaceDelete, workspaceList, writePlatformConfig };
|