diff --git a/bin/si-sdf-api-test/sdf_api_client.ts b/bin/si-sdf-api-test/sdf_api_client.ts index de02fe176e..11f78f848b 100644 --- a/bin/si-sdf-api-test/sdf_api_client.ts +++ b/bin/si-sdf-api-test/sdf_api_client.ts @@ -156,6 +156,21 @@ export const ROUTES = { `/v2/workspaces/${vars.workspaceId}/change-sets/${vars.changeSetId}/index/multi_mjolnir`, method: "POST", }, + deployment_mjolnir: { + path: (vars: ROUTE_VARS) => + `/v2/workspaces/${vars.workspaceId}/mjolnir?kind=${vars.referenceKind}&id=${vars.materializedViewId}`, + method: "POST", + }, + deployment_multi_mjolnir: { + path: (vars: ROUTE_VARS) => + `/v2/workspaces/${vars.workspaceId}/multi_mjolnir`, + method: "POST", + }, + deployment_index: { + path: (vars: ROUTE_VARS) => + `/v2/workspaces/${vars.workspaceId}/deployment_index`, + method: "GET", + }, // Websockets ----------------------------------------- workspace_updates_ws: { @@ -329,7 +344,7 @@ export class SdfApiClient { await retryUntil( async () => { - const dvuRoots = await this.mjolnir( + const dvuRoots = await this.changeSetMjolnir( changeSetId, "DependentValueComponentList", this.workspaceId, @@ -377,7 +392,7 @@ export class SdfApiClient { } // Helper functions for interacting with MVs - public async mjolnir( + public async changeSetMjolnir( changeSetId: string, kind: string, id: string, @@ -414,7 +429,7 @@ export class SdfApiClient { return null; } - public async multiMjolnir( + public async changeSetMultiMjolnir( changeSetId: string, mvs: { kind: string; id: string }[], ) { @@ -451,6 +466,86 @@ export class SdfApiClient { } } + public async deploymentMultiMjolnir(mvs: { kind: string; id: string }[]) { + const response = await this.call( + { + route: "deployment_multi_mjolnir", + body: { requests: mvs }, + }, + true, + ); + + if (response?.status === 200) { + try { + const json = await response.json(); + if (json.failed && json.failed.length > 0) { + console.warn( + "Some MVs were not found during multi mjolnir:", + json.failed, + ); + } + return json.successful.map((v: any) => v.frontEndObject.data); + } catch (err) { + console.error("Error trying to parse response body as JSON", err); + throw new Error(`Error trying to parse response body as JSON: ${err}`); + } + } else { + // Fail on non-200 errors + console.error( + `Error ${response.status}: Unable to fetch multiple Deployment MVs:`, + await response.text(), + ); + throw new Error(`Error ${response.status}: ${await response.text()}`); + } + } + + public async fetchDeploymentIndex(): Promise { + const response = await this.call( + { + route: "deployment_index", + }, + true, + ); + if (response?.status === 200) { + const json = await response.json(); + return json; + } else { + console.warn(`Deployment index missing! This is bad!`); + throw new Error(`Deployment index missing! This is bad!`); + } + } + + public async deploymentMjolnir( + kind: string, + id: string, + ): Promise { + const response = await this.call( + { + route: "deployment_mjolnir", + routeVars: { materializedViewId: id, referenceKind: kind }, + }, + true, + ); + if (response?.status === 200) { + try { + const json = await response.json(); + return json.data; + } catch (err) { + console.error("Error trying to parse response body as JSON", err); + } + } else { + console.warn( + `Deployment Materialized view for ${kind} with ID ${id} not found`, + ); + throw new Error( + "Deployment Materialized view not found for kind: " + + kind + + ", id: " + + id, + ); + } + } + public async fetchChangeSetIndex( changeSetId: string, timeout_ms: number = 150000, diff --git a/bin/si-sdf-api-test/test_helpers.ts b/bin/si-sdf-api-test/test_helpers.ts index f2db55368c..a1afab7dc3 100644 --- a/bin/si-sdf-api-test/test_helpers.ts +++ b/bin/si-sdf-api-test/test_helpers.ts @@ -254,40 +254,6 @@ export async function createComponent( return newComponentId; } -export function createComponentPayload( - schemaVariantCategoriesMV: any, - schemaName: string, -) { - const installedVariant = schemaVariantCategoriesMV.installed?.find( - (sv: any) => sv.schemaName === schemaName, - ); - if (installedVariant) { - return { - schemaVariantId: installedVariant.schemaVariantId, - x: "0", - y: "0", - height: "0", - width: "0", - parentId: null, - schemaType: "installed", - }; - } else { - const uninstalledVariant = schemaVariantCategoriesMV.uninstalled?.find( - (sv: any) => sv.schemaName === schemaName, - ); - assert(uninstalledVariant, `Expected to find ${schemaName} schema variant`); - return { - schemaId: uninstalledVariant.schemaId, - schemaType: "uninstalled", - x: "0", - y: "0", - height: "0", - width: "0", - parentId: null, - }; - } -} - // Func Helpers ------------------------------------------------------------ export async function getFuncRun( @@ -419,7 +385,7 @@ export async function abandon_all_change_sets(sdf: SdfApiClient) { } export async function getActions(sdf: SdfApiClient, changeSetId: string) { - const actions = await sdf.mjolnir( + const actions = await sdf.changeSetMjolnir( changeSetId, "ActionViewList", sdf.workspaceId, @@ -428,52 +394,85 @@ export async function getActions(sdf: SdfApiClient, changeSetId: string) { return actions; } -export async function getVariants(sdf: SdfApiClient, changeSetId: string) { - const schemas = await sdf.mjolnir( - changeSetId, - "SchemaVariantCategories", - sdf.workspaceId, +// Used to generate the correct payload for sdf +// If not given a Schema Id, assume it's a builtin, and find +// the Id by the name by looking at the CachedSchemas Deployment MV +// If given a schema Id, just try to find an installed one +export async function createComponentPayload( + sdf: SdfApiClient, + changeSetId: string, + schemaName: string, + schemaId?: string, +) { + const deploymentIndex = await sdf.fetchDeploymentIndex(); + // console.log(deploymentIndex); + + const cachedSchemasMV = deploymentIndex.frontEndObject.data.mvList.find( + (mv: any) => mv.kind === "CachedSchemas", ); - assert(schemas, "Expected to get schemas MV"); - - const installedList: { kind: string; id: string }[] = - schemas.categories.flatMap((c: any) => - c.schemaVariants - .filter((v: any) => v.type === "installed") - .map((v: any) => { - return { - kind: "SchemaVariant", - id: v.id, - }; - }), + const cachedSchemasMVId = cachedSchemasMV.id; + let actualSchemaId = undefined; + if (!schemaId) { + // Get the builtin version, so we can get the Schema Id as we only have the name + const builtins = await sdf.deploymentMjolnir( + "CachedSchemas", + cachedSchemasMVId, + ); + + assert(builtins, "Expected to get schemas MV"); + let foundSchema = builtins.schemas.find( + (schema: { id: string; name: string }) => schema.name === schemaName, ); - let installed = []; - if (installedList.length > 0) { - let installedResp = await sdf.multiMjolnir(changeSetId, installedList); - assert(installedResp, "Expected to get installed variants data"); - installed = installedResp; + assert(foundSchema, `Expected to find id for Schema Name ${schemaName}`); + actualSchemaId = foundSchema.id; + assert(actualSchemaId, `Expected to find id for Schema Name ${schemaName}`); + } else { + actualSchemaId = schemaId; } - const uninstalled = schemas.categories.flatMap((c: any) => - c.schemaVariants - .filter((v: any) => v.type === "uninstalled") - .map((v: any) => { - const uninstalledMeta = schemas.uninstalled?.[v.id]; - assert( - uninstalledMeta, - `Expected uninstalled metadata for schemaId ${v.id}`, - ); - return uninstalledMeta; - }), - ); - return { installed, uninstalled }; + assert(actualSchemaId, "we have a valid schema Id!"); + try { + // First is it installed? + const maybeInstalled = await sdf.changeSetMjolnir( + changeSetId, + "LuminorkDefaultVariant", + actualSchemaId, + ); + // if so, return it + return { + schemaVariantId: maybeInstalled.variantId, + x: "0", + y: "0", + height: "0", + width: "0", + parentId: null, + schemaType: "installed", + }; + } catch (e) { + console.log( + `LuminorkDefaultVariant not found for ${schemaName}, assuming it's uninstalled`, + ); + return { + schemaId: actualSchemaId, + schemaType: "uninstalled", + x: "0", + y: "0", + height: "0", + width: "0", + parentId: null, + }; + } } export async function getViews(sdf: SdfApiClient, changeSetId: string) { - const viewsList = await sdf.mjolnir(changeSetId, "ViewList", sdf.workspaceId); + const viewsList = await sdf.changeSetMjolnir( + changeSetId, + "ViewList", + sdf.workspaceId, + ); assert(viewsList, "Expected to get views MV"); let viewsToFetch = viewsList.views; - let views = await sdf.multiMjolnir(changeSetId, viewsToFetch); + let views = await sdf.changeSetMultiMjolnir(changeSetId, viewsToFetch); assert(views, "Expected to get views data"); return views; } @@ -493,7 +492,7 @@ export async function eventualMVAssert( } await retryUntil( async () => { - const mv = await sdf.mjolnir(changeSetId, kind, id); + const mv = await sdf.changeSetMjolnir(changeSetId, kind, id); if (mv) { try { if (assertFn(mv)) { diff --git a/bin/si-sdf-api-test/tests/0-add_action.ts b/bin/si-sdf-api-test/tests/0-add_action.ts index a8e2e8135c..bae82b65e1 100644 --- a/bin/si-sdf-api-test/tests/0-add_action.ts +++ b/bin/si-sdf-api-test/tests/0-add_action.ts @@ -1,6 +1,13 @@ import assert from "node:assert"; import { SdfApiClient } from "../sdf_api_client.ts"; -import { createComponent, createComponentPayload, eventualMVAssert, getActions, getVariants, getViews, runWithTemporaryChangeset } from "../test_helpers.ts"; +import { + createComponent, + createComponentPayload, + eventualMVAssert, + getActions, + getViews, + runWithTemporaryChangeset, +} from "../test_helpers.ts"; export default async function add_action(sdfApiClient: SdfApiClient) { return runWithTemporaryChangeset(sdfApiClient, add_action_inner); @@ -14,12 +21,14 @@ export async function add_action_inner( // Store the original length of actions to verify later assert(Array.isArray(data.actions), "Expected actions to be an array"); - const actionOriginalLength = data.actions.length; // Get all Schema Variants - let schemaVariants = await getVariants(sdfApiClient, changeSetId); - let createComponentBody = createComponentPayload(schemaVariants, "AWS::EC2::Instance"); + let createComponentBody = await createComponentPayload( + sdfApiClient, + changeSetId, + "AWS::EC2::Instance", + ); // Get the views and find the default one const views = await getViews(sdfApiClient, changeSetId); @@ -40,8 +49,13 @@ export async function add_action_inner( changeSetId, "ActionViewList", sdfApiClient.workspaceId, - (mv) => { return mv.actions.some((action: any) => action.componentId === newComponentId) && mv.actions.length === actionOriginalLength + 1; }, + (mv) => { + return ( + mv.actions.some( + (action: any) => action.componentId === newComponentId, + ) && mv.actions.length === actionOriginalLength + 1 + ); + }, "No action with the expected componentId found", ); - } diff --git a/bin/si-sdf-api-test/tests/1-create_and_apply_across_change_sets.ts b/bin/si-sdf-api-test/tests/1-create_and_apply_across_change_sets.ts index 03f715e83a..c4cae8eb1c 100644 --- a/bin/si-sdf-api-test/tests/1-create_and_apply_across_change_sets.ts +++ b/bin/si-sdf-api-test/tests/1-create_and_apply_across_change_sets.ts @@ -5,7 +5,6 @@ import { createComponent, createComponentPayload, eventualMVAssert, - getVariants, getViews, installModule, } from "../test_helpers.ts"; @@ -15,7 +14,8 @@ export default async function create_and_and_apply_across_change_sets( ) { return await create_and_and_apply_across_change_sets_inner(sdfApiClient); } -const TEST_RESOURCE_ACTION_MODULE_ID = "01JMJB1QW3M8D7MNN8NGBR739J"; +const TEST_RESOURCE_ACTION_MODULE_ID = "01JMJB1QW3M8D7MNN8NGBR739J"; // From module index +const TEST_RESOURCE_SCHEMA_ID = "01J85S2MXMFPJVW6FP3N9K4WSE"; // From module index - static id async function create_and_and_apply_across_change_sets_inner( sdf: SdfApiClient, ) { @@ -35,15 +35,15 @@ async function create_and_and_apply_across_change_sets_inner( const defaultView = views.find((v: any) => v.isDefault); assert(defaultView, "Expected to find a default view"); - let schemaVariants = await getVariants(sdf, changeSetId); - + let createComponentMaybeUninstalled = await createComponentPayload( + sdf, + changeSetId, + "TestResourceActions", + TEST_RESOURCE_SCHEMA_ID, + ); // first let's make sure our test asset is installed // this is really just so we can run this against any workspace - if ( - !schemaVariants.installed.some( - (v: any) => v.schemaName === "TestResourceActions", - ) - ) { + if (createComponentMaybeUninstalled.schemaType === "uninstalled") { const installResult = await installModule( sdf, changeSetId, @@ -54,7 +54,6 @@ async function create_and_and_apply_across_change_sets_inner( installResult[0]?.schemaVariantId, "Expected to get a schemaVariantId after installing TestResourceActions module", ); - const installedVariantId = installResult[0].schemaVariantId; console.log( "Installing TestResourceActions schema variant...", installResult, @@ -62,32 +61,24 @@ async function create_and_and_apply_across_change_sets_inner( await eventualMVAssert( sdf, changeSetId, - "SchemaVariantCategories", - sdf.workspaceId, + "LuminorkDefaultVariant", + TEST_RESOURCE_SCHEMA_ID, (mv) => { - const installedList: string[] = mv.categories.flatMap((c: any) => - c.schemaVariants - .filter((v: any) => v.type === "installed") - .map((v: any) => { - return v.id; - }), - ); - console.log("Installed Schema Variants:", installedList); - console.log("Expected Schema Variant ID:", installedVariantId); - return installedList.some((v: any) => v === installedVariantId); + return mv?.id === TEST_RESOURCE_SCHEMA_ID; }, "Expected TestResourceActions schema variant to be installed", ); - schemaVariants = await getVariants(sdf, changeSetId); } // Create a component with the TestResourceActions schema variant console.log( "Creating a component with the TestResourceActions schema variant...", ); - let createComponentBody = createComponentPayload( - schemaVariants, + let createComponentBody = await createComponentPayload( + sdf, + changeSetId, "TestResourceActions", + TEST_RESOURCE_SCHEMA_ID, ); const newComponentId = await createComponent( sdf, @@ -159,7 +150,7 @@ async function cleanupHead(sdf: SdfApiClient): Promise { const changeSetId = await createChangeSet(sdf); const workspaceId = sdf.workspaceId; - const components = await sdf.mjolnir( + const components = await sdf.changeSetMjolnir( changeSetId, "ComponentList", workspaceId, diff --git a/bin/si-sdf-api-test/tests/2-create_and_upgrade_component.ts b/bin/si-sdf-api-test/tests/2-create_and_upgrade_component.ts index efcadaac45..792bd2e5b7 100644 --- a/bin/si-sdf-api-test/tests/2-create_and_upgrade_component.ts +++ b/bin/si-sdf-api-test/tests/2-create_and_upgrade_component.ts @@ -1,6 +1,12 @@ import assert from "node:assert"; import { SdfApiClient } from "../sdf_api_client.ts"; -import { createComponent, createComponentPayload, eventualMVAssert, getVariants, getViews, runWithTemporaryChangeset } from "../test_helpers.ts"; +import { + createComponent, + createComponentPayload, + eventualMVAssert, + getViews, + runWithTemporaryChangeset, +} from "../test_helpers.ts"; export default async function create_and_upgrade_component( sdfApiClient: SdfApiClient, @@ -20,9 +26,11 @@ async function create_and_upgrade_component_inner( sdfApiClient: SdfApiClient, changeSetId: string, ) { - // Get all Schema Variants - let schemaVariants = await getVariants(sdfApiClient, changeSetId); - let createComponentBody = createComponentPayload(schemaVariants, "Region"); + let createComponentBody = await createComponentPayload( + sdfApiClient, + changeSetId, + "Region", + ); // Get the views and find the default one const views = await getViews(sdfApiClient, changeSetId); @@ -37,20 +45,37 @@ async function create_and_upgrade_component_inner( createComponentBody, ); assert(newComponentId, "Expected to get a component id after creation"); - const region = await sdfApiClient.mjolnir(changeSetId, "Component", newComponentId); + const region = await sdfApiClient.changeSetMjolnir( + changeSetId, + "Component", + newComponentId, + ); assert(region, "Expected to get a region after creation"); const originalSchemaVariantId = region.schemaVariantId.id; - assert(originalSchemaVariantId, "Expected to get a schema variant id after creation"); + assert( + originalSchemaVariantId, + "Expected to get a schema variant id after creation", + ); const schemaId = region.schemaId; assert(schemaId, "Expected to get a schema id after creation"); // ensure this schema is the default variant and there is no editing variant - const schemaMembers = await sdfApiClient.mjolnir(changeSetId, "SchemaMembers", schemaId); + const schemaMembers = await sdfApiClient.changeSetMjolnir( + changeSetId, + "SchemaMembers", + schemaId, + ); assert(schemaMembers, "Expected to get a schema after creation"); - assert(schemaMembers.defaultVariantId === originalSchemaVariantId, "Expected default variant to match original schema variant id"); - assert(schemaMembers.editingVariantId === null, "Expected no editing variant for the schema"); + assert( + schemaMembers.defaultVariantId === originalSchemaVariantId, + "Expected default variant to match original schema variant id", + ); + assert( + schemaMembers.editingVariantId === null, + "Expected no editing variant for the schema", + ); - // unlock the region schema variant + // unlock the region schema variant const newSchemaVariant = await sdfApiClient.call({ route: "create_unlocked_copy", routeVars: { @@ -59,7 +84,10 @@ async function create_and_upgrade_component_inner( schemaVariantId: originalSchemaVariantId, }, }); - assert(newSchemaVariant, "Expected to get a new schema variant after unlocking"); + assert( + newSchemaVariant, + "Expected to get a new schema variant after unlocking", + ); console.log("Created new schema variant:", newSchemaVariant); // see that the component has an upgrade available @@ -68,7 +96,9 @@ async function create_and_upgrade_component_inner( changeSetId, "SchemaMembers", schemaId, - (mv) => mv.defaultVariantId === originalSchemaVariantId && mv.editingVariantId !== null, + (mv) => + mv.defaultVariantId === originalSchemaVariantId && + mv.editingVariantId !== null, "Component MV should have upgradeAvailable set to true", ); // upgrade the component diff --git a/bin/si-sdf-api-test/tests/4-create_two_components_connect_and_propagate.ts b/bin/si-sdf-api-test/tests/4-create_two_components_connect_and_propagate.ts index 4b52d49a18..7b062c1522 100644 --- a/bin/si-sdf-api-test/tests/4-create_two_components_connect_and_propagate.ts +++ b/bin/si-sdf-api-test/tests/4-create_two_components_connect_and_propagate.ts @@ -4,9 +4,7 @@ import { createComponent, createComponentPayload, eventualMVAssert, - getVariants, getViews, - retryWithBackoff, runWithTemporaryChangeset, } from "../test_helpers.ts"; @@ -31,25 +29,26 @@ async function create_two_components_connect_and_propagate_inner( sdf: SdfApiClient, changeSetId: string, ) { - // Get the schema variants (uninstalled and installed) - let schemaVariants = await getVariants(sdf, changeSetId); - // Get the views and find the default one const views = await getViews(sdf, changeSetId); const defaultView = views.find((v: any) => v.isDefault); assert(defaultView, "Expected to find a default view"); // Create three components, an EC2 Instance, a Region, and a Credential - let createEC2ComponentBody = createComponentPayload( - schemaVariants, + let createEC2ComponentBody = await createComponentPayload( + sdf, + changeSetId, "AWS::EC2::Instance", ); - let createRegionComponentBody = createComponentPayload( - schemaVariants, + + let createRegionComponentBody = await createComponentPayload( + sdf, + changeSetId, "Region", ); - let createCredentialComponentBody = createComponentPayload( - schemaVariants, + let createCredentialComponentBody = await createComponentPayload( + sdf, + changeSetId, "AWS Credential", ); const newEC2ComponentId = await createComponent( diff --git a/bin/si-sdf-api-test/tests/5-emulate_paul_stack.ts b/bin/si-sdf-api-test/tests/5-emulate_paul_stack.ts index 49a2aec11e..4baa6b6894 100644 --- a/bin/si-sdf-api-test/tests/5-emulate_paul_stack.ts +++ b/bin/si-sdf-api-test/tests/5-emulate_paul_stack.ts @@ -5,10 +5,9 @@ import { runWithTemporaryChangeset, sleepBetween, createComponent, - getVariants, - createComponentPayload, getViews, eventualMVAssert, + createComponentPayload, } from "../test_helpers.ts"; export default async function emulate_paul_stack(sdfApiClient: SdfApiClient) { @@ -20,9 +19,11 @@ async function emulate_paul_stack_inner( sdf: SdfApiClient, changeSetId: string, ) { - // Get the schema variants (uninstalled and installed) - let schemaVariants = await getVariants(sdf, changeSetId); - let createRegionBody = createComponentPayload(schemaVariants, "Region"); + let createRegionBody = await createComponentPayload( + sdf, + changeSetId, + "Region", + ); // Get the views and find the default one const views = await getViews(sdf, changeSetId); @@ -49,10 +50,12 @@ async function emulate_paul_stack_inner( }, }); - - // CREATE VPC - let createVPCBody = createComponentPayload(schemaVariants, "AWS::EC2::VPC"); + let createVPCBody = await createComponentPayload( + sdf, + changeSetId, + "AWS::EC2::VPC", + ); const vpcComponentId = await createComponent( sdf, changeSetId, @@ -70,10 +73,10 @@ async function emulate_paul_stack_inner( }, body: { "/domain/extra/Region": { - "$source": { - "component": regionComponentId, - "path": "/domain/region", - } + $source: { + component: regionComponentId, + path: "/domain/region", + }, }, }, }); @@ -84,14 +87,14 @@ async function emulate_paul_stack_inner( changeSetId, "AttributeTree", vpcComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/extra/Region" && - av.externalSources.length === 1, - ), + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => + av.path === "/domain/extra/Region" && av.externalSources.length === 1, + ), "Expected VPC to be subscribed to Region", ); - // CONFIGURE VPC const updateVpcResponse = await sdf.call({ route: "attributes", @@ -113,17 +116,20 @@ async function emulate_paul_stack_inner( changeSetId, "AttributeTree", vpcComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/CidrBlock" && - av.value === "10.0.0.0/16" - ), - "Expected VPC to have CidrBlock set to 10.0.0.0/16" + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => + av.path === "/domain/CidrBlock" && av.value === "10.0.0.0/16", + ), + "Expected VPC to have CidrBlock set to 10.0.0.0/16", ); - // Public Subnet Components - const createSubnetBody = createComponentPayload(schemaVariants, "AWS::EC2::Subnet"); - + const createSubnetBody = await createComponentPayload( + sdf, + changeSetId, + "AWS::EC2::Subnet", + ); for (const { index, data } of [ { CidrBlock: "10.0.128.0/20", AvailabilityZone: "us-east-1a" }, @@ -147,15 +153,15 @@ async function emulate_paul_stack_inner( }, body: { "/domain/extra/Region": { - "$source": { - "component": regionComponentId, - "path": "/domain/region", + $source: { + component: regionComponentId, + path: "/domain/region", }, }, "/domain/VpcId": { - "$source": { - "component": vpcComponentId, - "path": "/resource_value/VpcId", + $source: { + component: vpcComponentId, + path: "/resource_value/VpcId", }, }, }, @@ -166,11 +172,13 @@ async function emulate_paul_stack_inner( changeSetId, "AttributeTree", subnetComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/extra/Region" && - av.externalSources.length === 1 && - av.externalSources[0].path === "/domain/region", - ), + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => + av.path === "/domain/extra/Region" && + av.externalSources.length === 1 && + av.externalSources[0].path === "/domain/region", + ), "Expected Subnet to be subscribed to Region", ); @@ -210,7 +218,11 @@ async function emulate_paul_stack_inner( }); await sdf.waitForDVURoots(changeSetId, 500, 30000); // verify that the region value propagated to the vpc and subnets - const componentsToCheck = await sdf.mjolnir(changeSetId, "ComponentList", sdf.workspaceId); + const componentsToCheck = await sdf.changeSetMjolnir( + changeSetId, + "ComponentList", + sdf.workspaceId, + ); const componentIds = componentsToCheck.components.map((c) => c.id); for (const id of componentIds) { await eventualMVAssert( @@ -218,17 +230,15 @@ async function emulate_paul_stack_inner( changeSetId, "AttributeTree", id, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/extra/Region" && - av.value === "us-east-1", - ) || Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/region" && - av.value === "us-east-1", - ), + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => + av.path === "/domain/extra/Region" && av.value === "us-east-1", + ) || + Object.values(mv.attributeValues).some( + (av: any) => av.path === "/domain/region" && av.value === "us-east-1", + ), `Expected component ${id} to have region set to us-east-1`, ); } } - - - diff --git a/bin/si-sdf-api-test/tests/7-emulate_authoring.ts b/bin/si-sdf-api-test/tests/7-emulate_authoring.ts index c1dbf08ca5..dc3f384da7 100644 --- a/bin/si-sdf-api-test/tests/7-emulate_authoring.ts +++ b/bin/si-sdf-api-test/tests/7-emulate_authoring.ts @@ -2,217 +2,255 @@ import assert from "node:assert"; import { SdfApiClient } from "../sdf_api_client.ts"; import { - runWithTemporaryChangeset, - sleepBetween, - createAsset, - updateAssetCode, - nilId, - createQualification, - eventualMVAssert, - getViews, + runWithTemporaryChangeset, + sleepBetween, + createAsset, + updateAssetCode, + nilId, + createQualification, + eventualMVAssert, + getViews, } from "../test_helpers.ts"; export default async function emulate_authoring(sdfApiClient: SdfApiClient) { - await sleepBetween(0, 750); - return runWithTemporaryChangeset(sdfApiClient, emulate_authoring_inner); + await sleepBetween(0, 750); + return runWithTemporaryChangeset(sdfApiClient, emulate_authoring_inner); } -async function emulate_authoring_inner(sdf: SdfApiClient, - changeSetId: string, -) { - - // Get the views and find the default one - const views = await getViews(sdf, changeSetId); - const defaultView = views.find((v: any) => v.isDefault); - assert(defaultView, "Expected to find a default view"); - - // Create new asset - let schemaVariantId = await createAsset(sdf, changeSetId, "doubler"); - - // wait for and verify schema variant MV - await eventualMVAssert( - sdf, - changeSetId, - "SchemaVariant", - schemaVariantId, - (mv) => mv.id === schemaVariantId, - "SchemaVariant MV should exist and have matching id" - ); - - // Update Code and Regenerate - schemaVariantId = await updateAssetCode(sdf, changeSetId, schemaVariantId, doublerAssetCode); - - await eventualMVAssert( - sdf, - changeSetId, - "SchemaVariant", - schemaVariantId, - (mv) => { - const props = Object.values(mv.propTree?.props) || []; - return mv.id === schemaVariantId && - props.some((p: any) => p.path === "root/domain/input") && - props.some((p: any) => p.path === "root/domain/doubled"); - }, - "SchemaVariant MV should exist and have added input/doubled props" - ); - let doublerVariant = await sdf.mjolnir(changeSetId, "SchemaVariant", schemaVariantId); - assert(doublerVariant?.propTree?.props, "Expected props list"); - - let doublerProps = Object.values(doublerVariant.propTree.props); - - assert(Array.isArray(doublerProps), "Expected props to be an array"); - // Add an attribute function - const outputProp = doublerProps.find((p: any) => p.path === "root/domain/doubled"); - assert(outputProp, "Expected to find doubled prop"); - let inputProp: any = doublerProps.find((p: any) => p.path === "root/domain/input"); - assert(inputProp, "Expected to find input prop"); - const args = [ - { - name: "input", - kind: "string", - propId: inputProp.id, - inputSocketId: null, - }, - ]; - - const doubleFuncId = await createAttributeFunction(sdf, changeSetId, "double", doublerVariant.id, doubleFuncCode, outputProp.id, args); - let createComponentBody = { - "schemaVariantId": schemaVariantId, - "x": "0", - "y": "0", - "height": "0", - "width": "0", - "parentId": null, - "schemaType": "installed" - - }; - - // create a component for the doubler - const createComponentResp = await sdf.call({ - route: "create_component_v2", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - viewId: defaultView.id, - }, - body: createComponentBody, - }); - const doublerComponentId = createComponentResp?.componentId; - assert(doublerComponentId, "Expected to get a component id after creation"); - await eventualMVAssert( - sdf, - changeSetId, - "Component", - doublerComponentId, - (mv) => mv.id === doublerComponentId && mv.qualificationTotals.succeeded === 0, - "Component MV should exist" - ); - - // update input prop to be a number - const updateRegionResponse = await sdf.call({ - route: "attributes", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - componentId: doublerComponentId, - }, - body: { - "/domain/input": "2", - }, - }); - - await eventualMVAssert( - sdf, - changeSetId, - "AttributeTree", - doublerComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/input" && - av.value === "2", - ), - "Expected value to be set for domain/input", - ); - - - // now add a qualification and check that the component gets it - const qualification = await createQualification( - sdf, - changeSetId, "doublerQualification", - schemaVariantId, - doublerQualificationCode - ); - - - // it is failing - await eventualMVAssert( - sdf, - changeSetId, - "Component", - doublerComponentId, - (mv) => mv.qualificationTotals.failed === 1, - "Component should have a failed qualification now", - ); - - - await eventualMVAssert( - sdf, - changeSetId, - "AttributeTree", - doublerComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/doubled" && - av.value === "4", - ), - "Expected doubled attribute value to be 4", - ); - - // Now let's add a prop, regenerate, add an attribute func, and make sure it all works - schemaVariantId = await updateAssetCode(sdf, changeSetId, schemaVariantId, doublerAssetCodeAddedTripled); - await eventualMVAssert( - sdf, - changeSetId, - "SchemaVariant", - schemaVariantId, - (mv) => Object.values(mv.propTree.props).some((p: any) => p.path === "root/domain/tripled"), - "SchemaVariant should have new tripled prop" - ); - - doublerVariant = await sdf.mjolnir(changeSetId, "SchemaVariant", schemaVariantId); - doublerProps = Object.values(doublerVariant.propTree.props); - assert(Array.isArray(doublerProps), "Expected props to be an array"); - - // Add an attribute function - const tripleProp = doublerProps.find((p: any) => p.path === "root/domain/tripled"); - assert(tripleProp, "Expected to find output prop"); - inputProp = doublerProps.find((p: any) => p.path === "root/domain/input"); - assert(inputProp, "Expected to find input prop"); - const triplerArgs = [ - { - name: "input", - kind: "string", - propId: inputProp.id, - inputSocketId: null, - }, - ]; - - const tripleFuncId = await createAttributeFunction(sdf, changeSetId, "triple", schemaVariantId, tripleFuncCode, tripleProp.id, triplerArgs); - - // now ensure the component has the new prop too and it's value has been updated - await eventualMVAssert( - sdf, - changeSetId, - "AttributeTree", - doublerComponentId, - (mv) => Object.values(mv.attributeValues).some( - (av: any) => av.path === "/domain/tripled" && - av.value === "6", - ), - "Expected tripled attribute value to be 6", - ); - +async function emulate_authoring_inner(sdf: SdfApiClient, changeSetId: string) { + // Get the views and find the default one + const views = await getViews(sdf, changeSetId); + const defaultView = views.find((v: any) => v.isDefault); + assert(defaultView, "Expected to find a default view"); + + // Create new asset + let schemaVariantId = await createAsset(sdf, changeSetId, "doubler"); + + // wait for and verify schema variant MV + await eventualMVAssert( + sdf, + changeSetId, + "SchemaVariant", + schemaVariantId, + (mv) => mv.id === schemaVariantId, + "SchemaVariant MV should exist and have matching id", + ); + + // Update Code and Regenerate + schemaVariantId = await updateAssetCode( + sdf, + changeSetId, + schemaVariantId, + doublerAssetCode, + ); + + await eventualMVAssert( + sdf, + changeSetId, + "SchemaVariant", + schemaVariantId, + (mv) => { + const props = Object.values(mv.propTree?.props) || []; + return ( + mv.id === schemaVariantId && + props.some((p: any) => p.path === "root/domain/input") && + props.some((p: any) => p.path === "root/domain/doubled") + ); + }, + "SchemaVariant MV should exist and have added input/doubled props", + ); + let doublerVariant = await sdf.changeSetMjolnir( + changeSetId, + "SchemaVariant", + schemaVariantId, + ); + assert(doublerVariant?.propTree?.props, "Expected props list"); + + let doublerProps = Object.values(doublerVariant.propTree.props); + + assert(Array.isArray(doublerProps), "Expected props to be an array"); + // Add an attribute function + const outputProp = doublerProps.find( + (p: any) => p.path === "root/domain/doubled", + ); + assert(outputProp, "Expected to find doubled prop"); + let inputProp: any = doublerProps.find( + (p: any) => p.path === "root/domain/input", + ); + assert(inputProp, "Expected to find input prop"); + const args = [ + { + name: "input", + kind: "string", + propId: inputProp.id, + inputSocketId: null, + }, + ]; + + const doubleFuncId = await createAttributeFunction( + sdf, + changeSetId, + "double", + doublerVariant.id, + doubleFuncCode, + outputProp.id, + args, + ); + let createComponentBody = { + schemaVariantId: schemaVariantId, + x: "0", + y: "0", + height: "0", + width: "0", + parentId: null, + schemaType: "installed", + }; + + // create a component for the doubler + const createComponentResp = await sdf.call({ + route: "create_component_v2", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + viewId: defaultView.id, + }, + body: createComponentBody, + }); + const doublerComponentId = createComponentResp?.componentId; + assert(doublerComponentId, "Expected to get a component id after creation"); + await eventualMVAssert( + sdf, + changeSetId, + "Component", + doublerComponentId, + (mv) => + mv.id === doublerComponentId && mv.qualificationTotals.succeeded === 0, + "Component MV should exist", + ); + + // update input prop to be a number + const updateRegionResponse = await sdf.call({ + route: "attributes", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + componentId: doublerComponentId, + }, + body: { + "/domain/input": "2", + }, + }); + + await eventualMVAssert( + sdf, + changeSetId, + "AttributeTree", + doublerComponentId, + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => av.path === "/domain/input" && av.value === "2", + ), + "Expected value to be set for domain/input", + ); + + // now add a qualification and check that the component gets it + const qualification = await createQualification( + sdf, + changeSetId, + "doublerQualification", + schemaVariantId, + doublerQualificationCode, + ); + + // it is failing + await eventualMVAssert( + sdf, + changeSetId, + "Component", + doublerComponentId, + (mv) => mv.qualificationTotals.failed === 1, + "Component should have a failed qualification now", + ); + + await eventualMVAssert( + sdf, + changeSetId, + "AttributeTree", + doublerComponentId, + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => av.path === "/domain/doubled" && av.value === "4", + ), + "Expected doubled attribute value to be 4", + ); + + // Now let's add a prop, regenerate, add an attribute func, and make sure it all works + schemaVariantId = await updateAssetCode( + sdf, + changeSetId, + schemaVariantId, + doublerAssetCodeAddedTripled, + ); + await eventualMVAssert( + sdf, + changeSetId, + "SchemaVariant", + schemaVariantId, + (mv) => + Object.values(mv.propTree.props).some( + (p: any) => p.path === "root/domain/tripled", + ), + "SchemaVariant should have new tripled prop", + ); + + doublerVariant = await sdf.changeSetMjolnir( + changeSetId, + "SchemaVariant", + schemaVariantId, + ); + doublerProps = Object.values(doublerVariant.propTree.props); + assert(Array.isArray(doublerProps), "Expected props to be an array"); + + // Add an attribute function + const tripleProp = doublerProps.find( + (p: any) => p.path === "root/domain/tripled", + ); + assert(tripleProp, "Expected to find output prop"); + inputProp = doublerProps.find((p: any) => p.path === "root/domain/input"); + assert(inputProp, "Expected to find input prop"); + const triplerArgs = [ + { + name: "input", + kind: "string", + propId: inputProp.id, + inputSocketId: null, + }, + ]; + + const tripleFuncId = await createAttributeFunction( + sdf, + changeSetId, + "triple", + schemaVariantId, + tripleFuncCode, + tripleProp.id, + triplerArgs, + ); + + // now ensure the component has the new prop too and it's value has been updated + await eventualMVAssert( + sdf, + changeSetId, + "AttributeTree", + doublerComponentId, + (mv) => + Object.values(mv.attributeValues).some( + (av: any) => av.path === "/domain/tripled" && av.value === "6", + ), + "Expected tripled attribute value to be 6", + ); } - const doubleFuncCode = `async function main(input: Input): Promise < Output > { const number = parseInt(input?.input); if (!number) { @@ -304,140 +342,143 @@ const doublerQualificationCode = `async function main(component: Input): Promise // REQUEST HELPERS WITH VALIDATIONS -async function createAttributeFunction(sdf: SdfApiClient, changeSetId: string, name: string, schemaVariantId: string, code: string, outputLocationId: string, funcArguments: any[]) { - const createFuncPayload = { - name, - displayName: name, - description: "", - binding: { - funcId: nilId, - schemaVariantId: schemaVariantId, - bindingKind: "attribute", - argumentBindings: [], - propId: outputLocationId, - }, - kind: "Attribute", - requestUlid: changeSetId, +async function createAttributeFunction( + sdf: SdfApiClient, + changeSetId: string, + name: string, + schemaVariantId: string, + code: string, + outputLocationId: string, + funcArguments: any[], +) { + const createFuncPayload = { + name, + displayName: name, + description: "", + binding: { + funcId: nilId, + schemaVariantId: schemaVariantId, + bindingKind: "attribute", + argumentBindings: [], + propId: outputLocationId, + }, + kind: "Attribute", + requestUlid: changeSetId, + }; + + const createFuncResp = await sdf.call({ + route: "create_func", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + }, + body: createFuncPayload, + }); + + // now list funcs and let's make sure we see it + const funcs = await sdf.call({ + route: "func_list", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + }, + }); + + const createdFunc = funcs.find((f) => f.name === name); + assert(createdFunc, "Expected to find newly created func"); + const funcId = createdFunc.funcId; + const codePayload = { + code, + requestUlid: changeSetId, + }; + + // save the code + const updateCodeResp = await sdf.call({ + route: "update_func_code", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + funcId, + }, + body: codePayload, + }); + + // create func arguments + let numArgs = 0; + for (const funcArg of funcArguments) { + // create the argument + let argPayload = { + created_at: new Date(), + updated_at: new Date(), + name: funcArg.name, + id: nilId, + kind: funcArg.kind, + requestUlid: changeSetId, }; - - const createFuncResp = await sdf.call({ - route: "create_func", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - }, - body: createFuncPayload, + const createArgResp = await sdf.call({ + route: "create_func_arg", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + funcId, + }, + body: argPayload, }); - - // now list funcs and let's make sure we see it - const funcs = await sdf.call({ - route: "func_list", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, + const args = createArgResp.arguments; + assert(Array.isArray(createArgResp?.arguments), "Expected arguments list"); + numArgs++; + assert( + createArgResp?.arguments.length === numArgs, + `Expected ${numArgs} but found ${createArgResp?.arguments.length}`, + ); + const createdArg = args.find((arg) => arg.name === funcArg.name); + const attributePrototypeArgumentId = createdArg.id; + const attributePrototypeId = + createArgResp?.bindings[0].attributePrototypeId; + // now update the argument bindings + + const bindingPayload = { + funcId, + bindings: [ + { + bindingKind: "attribute", + attributePrototypeId: attributePrototypeId, + funcId, + propId: outputLocationId, + componentId: null, + outputSocketId: null, + schemaVariantId, + argumentBindings: [ + { + funcArgumentId: createdArg.id, + propId: funcArg.propId, + attributePrototypeArgumentId: attributePrototypeArgumentId, + inputSocketId: funcArg.inputSocketId, + }, + ], }, - }); - - const createdFunc = funcs.find((f) => f.name === name); - assert(createdFunc, "Expected to find newly created func"); - const funcId = createdFunc.funcId; - const codePayload = { - code, - requestUlid: changeSetId, + ], }; - - // save the code - const updateCodeResp = await sdf.call({ - route: "update_func_code", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - funcId, - }, - body: codePayload, + const updateBindingResp = await sdf.call({ + route: "create_func_binding", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + funcId, + }, + body: bindingPayload, }); - // create func arguments - let numArgs = 0; - for (const funcArg of funcArguments) { - // create the argument - let argPayload = { - created_at: new Date(), - updated_at: new Date(), - name: funcArg.name, - id: nilId, - kind: funcArg.kind, - requestUlid: changeSetId, - }; - const createArgResp = await sdf.call({ - route: "create_func_arg", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - funcId, - }, - body: argPayload, - }); - const args = createArgResp.arguments; - assert( - Array.isArray(createArgResp?.arguments), - "Expected arguments list", - ); - numArgs++; - assert(createArgResp?.arguments.length === numArgs, `Expected ${numArgs} but found ${createArgResp?.arguments.length}`); - const createdArg = args.find((arg) => arg.name === funcArg.name); - const attributePrototypeArgumentId = createdArg.id; - const attributePrototypeId = createArgResp?.bindings[0].attributePrototypeId; - // now update the argument bindings - - const bindingPayload = { - funcId, - bindings: [ - { - bindingKind: "attribute", - attributePrototypeId: attributePrototypeId, - funcId, - propId: outputLocationId, - componentId: null, - outputSocketId: null, - schemaVariantId, - argumentBindings: [ - { - funcArgumentId: createdArg.id, - propId: funcArg.propId, - attributePrototypeArgumentId: attributePrototypeArgumentId, - inputSocketId: funcArg.inputSocketId, - } - ] - } - ] - } - const updateBindingResp = await sdf.call({ - route: "create_func_binding", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - funcId, - }, - body: bindingPayload, - }); - - assert( - Array.isArray(updateBindingResp), - "Expected bindings list", - ); - assert( - Array.isArray(updateBindingResp[0].argumentBindings), - "Expected argument bindings list", - ); - assert( - updateBindingResp[0].argumentBindings.length === numArgs, - "Expected argument bindings list", - ); - } - - return funcId; + assert(Array.isArray(updateBindingResp), "Expected bindings list"); + assert( + Array.isArray(updateBindingResp[0].argumentBindings), + "Expected argument bindings list", + ); + assert( + updateBindingResp[0].argumentBindings.length === numArgs, + "Expected argument bindings list", + ); + } + return funcId; } - - diff --git a/bin/si-sdf-api-test/tests/8-check_mjolnir.ts b/bin/si-sdf-api-test/tests/8-check_mjolnir.ts index 4c9adabed3..33c2485e20 100644 --- a/bin/si-sdf-api-test/tests/8-check_mjolnir.ts +++ b/bin/si-sdf-api-test/tests/8-check_mjolnir.ts @@ -1,6 +1,11 @@ import assert from "node:assert"; import { SdfApiClient } from "../sdf_api_client.ts"; -import { eventualMVAssert, getVariants, runWithTemporaryChangeset, createComponentPayload, getViews } from "../test_helpers.ts"; +import { + eventualMVAssert, + runWithTemporaryChangeset, + getViews, + createComponentPayload, +} from "../test_helpers.ts"; // ========================== // Tunables for testing here! @@ -8,116 +13,123 @@ const SCHEMA_NAME = "AWS::EC2::KeyPair"; // the schema name to be used for the t // ========================== export default async function check_mjolnir( - sdfApiClient: SdfApiClient, - changeSetId: string, + sdfApiClient: SdfApiClient, + changeSetId: string, ) { - if (changeSetId) { - return await check_mjolnir_inner(sdfApiClient, changeSetId); - } else { - return runWithTemporaryChangeset(sdfApiClient, check_mjolnir_inner); - } + if (changeSetId) { + return await check_mjolnir_inner(sdfApiClient, changeSetId); + } else { + return runWithTemporaryChangeset(sdfApiClient, check_mjolnir_inner); + } } -async function check_mjolnir_inner( - sdf: SdfApiClient, - changeSetId: string, -) { - - // Get the schema variants (uninstalled and installed) - let schemaVariants = await getVariants(sdf, changeSetId); - let createComponentBody = createComponentPayload(schemaVariants, SCHEMA_NAME); - - // Get the views and find the default one - const views = await getViews(sdf, changeSetId); - const defaultView = views.find((v: any) => v.isDefault); - assert(defaultView, "Expected to find a default view"); +async function check_mjolnir_inner(sdf: SdfApiClient, changeSetId: string) { + // Get the schema variants (uninstalled and installed) + let createComponentBody = await createComponentPayload( + sdf, + changeSetId, + SCHEMA_NAME, + ); - // Create a Component - const createComponentResp = await sdf.call({ - route: "create_component_v2", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - viewId: defaultView.id, - }, - body: createComponentBody, - }); - const { newComponentId, newComponentName } = { newComponentId: createComponentResp?.componentId, newComponentName: createComponentResp?.materializedView?.name }; - assert(newComponentId, "Expected to get a component id after creation"); + // Get the views and find the default one + const views = await getViews(sdf, changeSetId); + const defaultView = views.find((v: any) => v.isDefault); + assert(defaultView, "Expected to find a default view"); - // Wait for and verify component MV - await eventualMVAssert( - sdf, - changeSetId, - "Component", - newComponentId, - (mv) => mv.name === newComponentName, - "Component MV should exist and have matching name" - ); - const componentMV = await sdf.mjolnir(changeSetId, "Component", newComponentId); - assert(componentMV, "Expected to get a component schema variant id after creation"); - const schemaVariantId = componentMV.schemaVariantId.id; - // Delete the Component - const deleteComponentPayload = { - componentIds: [newComponentId], - forceErase: false, - }; - await sdf.call({ - route: "delete_components_v2", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - }, - body: deleteComponentPayload, - }); + // Create a Component + const createComponentResp = await sdf.call({ + route: "create_component_v2", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + viewId: defaultView.id, + }, + body: createComponentBody, + }); + const { newComponentId, newComponentName } = { + newComponentId: createComponentResp?.componentId, + newComponentName: createComponentResp?.materializedView?.name, + }; + assert(newComponentId, "Expected to get a component id after creation"); - // Verify component deletion - await eventualMVAssert( - sdf, - changeSetId, - "ComponentList", - sdf.workspaceId, - (mv) => mv.components.length === 0, - "Should have no components after deletion" - ); + // Wait for and verify component MV + await eventualMVAssert( + sdf, + changeSetId, + "Component", + newComponentId, + (mv) => mv.name === newComponentName, + "Component MV should exist and have matching name", + ); + const componentMV = await sdf.changeSetMjolnir( + changeSetId, + "Component", + newComponentId, + ); + assert( + componentMV, + "Expected to get a component schema variant id after creation", + ); + const schemaVariantId = componentMV.schemaVariantId.id; + // Delete the Component + const deleteComponentPayload = { + componentIds: [newComponentId], + forceErase: false, + }; + await sdf.call({ + route: "delete_components_v2", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + }, + body: deleteComponentPayload, + }); - // await an installed schema variant now - await eventualMVAssert( - sdf, - changeSetId, - "SchemaVariantCategories", - sdf.workspaceId, - (mv) => mv.categories.some((c: any) => c.schemaVariants.some((v: any) => { - if(v.type === "installed"){ - console.log("Found installed schema variant:", v.id, "Expected:", schemaVariantId); - } - return v.type === "installed" && v.id === schemaVariantId; - })), - "Schema variant should be installed", - ); - // create another one - schemaVariants = await getVariants(sdf, changeSetId); - createComponentBody = createComponentPayload(schemaVariants, SCHEMA_NAME); - const createComponent2Resp = await sdf.call({ - route: "create_component_v2", - routeVars: { - workspaceId: sdf.workspaceId, - changeSetId, - viewId: defaultView.id, - }, - body: createComponentBody, - }); - const { newComponentId2, newComponentName2 } = { newComponentId2: createComponent2Resp?.componentId, newComponentName2: createComponent2Resp?.materializedView?.name }; - assert(newComponentId2, "Expected to get a component id after creation"); - await eventualMVAssert( - sdf, - changeSetId, - "Component", - newComponentId2, - (mv) => mv.name === newComponentName2, - "Component MV should exist and have matching name" - ); + // Verify component deletion + await eventualMVAssert( + sdf, + changeSetId, + "ComponentList", + sdf.workspaceId, + (mv) => mv.components.length === 0, + "Should have no components after deletion", + ); + // await an installed schema variant now + await eventualMVAssert( + sdf, + changeSetId, + "LuminorkSchemaVariant", + schemaVariantId, + (mv) => mv.id === schemaVariantId, + "Schema variant should be installed", + ); + // create another one + createComponentBody = await createComponentPayload( + sdf, + changeSetId, + SCHEMA_NAME, + ); + const createComponent2Resp = await sdf.call({ + route: "create_component_v2", + routeVars: { + workspaceId: sdf.workspaceId, + changeSetId, + viewId: defaultView.id, + }, + body: createComponentBody, + }); + const { newComponentId2, newComponentName2 } = { + newComponentId2: createComponent2Resp?.componentId, + newComponentName2: createComponent2Resp?.materializedView?.name, + }; + assert(newComponentId2, "Expected to get a component id after creation"); + await eventualMVAssert( + sdf, + changeSetId, + "Component", + newComponentId2, + (mv) => mv.name === newComponentName2, + "Component MV should exist and have matching name", + ); } - - diff --git a/lib/dal/src/cached_module.rs b/lib/dal/src/cached_module.rs index afd5208b69..7c862e60ea 100644 --- a/lib/dal/src/cached_module.rs +++ b/lib/dal/src/cached_module.rs @@ -310,7 +310,7 @@ impl CachedModule { ctx: &DalContext, modules: &HashMap, module_index_client: ModuleIndexClient, - _edda_client: EddaClient, + edda_client: EddaClient, ) -> CachedModuleResult> { let hashes = modules.keys().map(ToOwned::to_owned).collect_vec(); let uncached_hashes = CachedModule::find_missing_entries(ctx, hashes).await?; @@ -355,11 +355,7 @@ impl CachedModule { } // Ask edda to rebuild the deployment MVs, which include the cached modules - // - // Until the performance issues in building the deployment-level MVs are fixed, - // this is only going to be deployed through the manual module sync process. - // - // edda_client.rebuild_for_deployment().await?; + edda_client.rebuild_for_deployment().await?; Ok(new_modules) }