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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ test-app$ yarn watch
| TEST_STACK_RETENTION_POLICY | After tests complete, `RETAIN`, `DELETE`, or `SELF_DESTRUCT` (delete after `TEST_SELF_DESTRUCT_DELAY_SECONDS`). Default: `SELF_DESTRUCT` |
| TEST_SELF_DESTRUCT_DELAY_SECONDS | Number of seconds to wait before self destructing the stack, Default: 12 hours (43200s) |
| CLEAN_UP_STACK | Deploys a CFN stack that can delete all of the test stacks (and itself) when invoked. Used the in Pull Request Closed CleanUp workflow to clean up after PRs. |
| TEST_DEPLOYER | Deploy using CDK/cloud formation (`CFN`) or using functionless's custom `NODE_CFN`, Default `CFN` |

### Website

Expand Down
7 changes: 1 addition & 6 deletions apps/fl-exp-simple/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,5 @@
"inlineSourceMap": true
},
"include": ["."],
"exclude": ["lib", "test", "node_modules"],
"references": [
{ "path": "../../packages/@functionless/aws-constructs" },
{ "path": "../../packages/@functionless/aws" },
{ "path": "../../packages/@functionless/fl-exp" }
]
"exclude": ["lib", "test", "node_modules"]
}
59 changes: 34 additions & 25 deletions apps/test-app/src/order-processing-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,32 +109,32 @@ failedOrderQueue.messages().forEach(async (message) => {
});
});

// processedOrderQueue.messages().forEach((order) => {
// console.log("processed order", order);
// });
processedOrderQueue.messages().forEach((order) => {
console.log("processed order", order);
});

new StepFunction(
stack,
"SendMessageBatch",
async (input: { messages: OrderPlacedEvent[] }) => {
await orderQueue.sendMessageBatch({
Entries: input.messages.map((message, idx) => ({
Id: `${idx}`,
MessageBody: message,
})),
});
}
);
// new StepFunction(
// stack,
// "SendMessageBatch",
// async (input: { messages: OrderPlacedEvent[] }) => {
// await orderQueue.sendMessageBatch({
// Entries: input.messages.map((message, idx) => ({
// Id: `${idx}`,
// MessageBody: message,
// })),
// });
// }
// );

new StepFunction(
stack,
"SendMessage",
async (input: { message: OrderPlacedEvent }) => {
await orderQueue.sendMessage({
MessageBody: input.message,
});
}
);
// new StepFunction(
// stack,
// "SendMessage",
// async (input: { message: OrderPlacedEvent }) => {
// await orderQueue.sendMessage({
// MessageBody: input.message,
// });
// }
// );

// TODO: implement retry logic once new intrinsics arrive
// @see https://github.com/functionless/functionless/pull/468
Expand Down Expand Up @@ -188,7 +188,7 @@ export interface UserPass {
const secret = new JsonSecret<UserPass>(stack, "JsonSecret", {
secretStringValue: SecretValue.unsafePlainText(
JSON.stringify({
username: "sam",
username: "sam2",
password: "sam",
})
),
Expand All @@ -204,3 +204,12 @@ new Function(stack, "SecretFunc", async (input: "get" | UserPass) => {
return response;
}
});

new JsonSecret<UserPass>(stack, "JsonSecret2", {
secretStringValue: SecretValue.unsafePlainText(
JSON.stringify({
username: "sam",
password: "sam",
})
),
});
3 changes: 2 additions & 1 deletion apps/test-app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
{
"name": "@functionless/language-service"
}
]
],
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"],
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
},
"devDependencies": {
"husky": "^8.0.1",
"lerna": "^5.5.4",
"lerna": "^5.6.1",
"lint-staged": "^13.0.3",
"turbo": "^1.5.5"
},
"dependencies": {
"typescript": "^4.8.4"
}
}
2 changes: 1 addition & 1 deletion packages/@functionless/ast/src/ensure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function ensure<Assert extends Assertion>(
.map((kind) =>
typeof kind === "number" ? getNodeKindName(kind) : kind
)
.join(", ")}`
.join(", ")}, found: ${JSON.stringify(item)}`
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@functionless/aws-constructs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"@aws-cdk/cloudformation-diff": "2.44.0",
"@aws-cdk/cx-api": "2.44.0",
"@aws-sdk/client-dynamodb": "^3.180.0",
"@aws-sdk/client-ssm": "^3.180.0",
"@functionless/jest": "^0.27.0",
"@functionless/formation": "*",
"@swc/jest": "^0.2.22",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^29.0.3",
Expand Down Expand Up @@ -64,8 +66,6 @@
"graphql-tag": "^2.12.6",
"jest": "^29.0.3",
"jest-junit": "^13",
"json-schema": "^0.4.0",
"npm-check-updates": "^15",
"prettier": "^2.7.1",
"promptly": "^3.2.0",
"proxy-agent": "^5.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import "jest";

import {
aws_dynamodb,
aws_sqs,
CfnOutput,
Duration,
RemovalPolicy,
} from "aws-cdk-lib";
import { aws_dynamodb, aws_sqs, Duration, RemovalPolicy } from "aws-cdk-lib";
import { Role } from "aws-cdk-lib/aws-iam";
import { SQSBatchResponse } from "aws-lambda";
import { Construct } from "constructs";
Expand Down Expand Up @@ -248,10 +242,7 @@ runtimeTestSuite<{
data: string;
}

const addr = new CfnOutput(scope, "out", { value: "" });
const bus = new EventBus<Event<Message>>(scope, "bus", {
eventBusName: addr.node.addr,
});
const bus = new EventBus<Event<Message>>(scope, "bus");

bus.resource.grantPutEventsTo(testRole);

Expand All @@ -273,7 +264,7 @@ runtimeTestSuite<{
return {
queue,
outputs: {
busName: addr.node.addr,
busName: bus.resource.eventBusName,
Comment on lines -276 to +267
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops lol. How did that ever work

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It did work, but the bus was a singleton.

},
};
},
Expand All @@ -288,10 +279,7 @@ runtimeTestSuite<{
data: string;
}

const addr = new CfnOutput(scope, "out", { value: "" });
const bus = new EventBus<Event<Message>>(scope, "bus", {
eventBusName: addr.node.addr,
});
const bus = new EventBus<Event<Message>>(scope, "bus");

bus.resource.grantPutEventsTo(testRole);

Expand Down Expand Up @@ -334,7 +322,7 @@ runtimeTestSuite<{
return {
queue,
outputs: {
busName: addr.node.addr,
busName: bus.resource.eventBusName,
messageGroupId: "busGroup",
},
};
Expand Down
89 changes: 70 additions & 19 deletions packages/@functionless/aws-constructs/test/runtime.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import * as cxapi from "@aws-cdk/cx-api";
import * as ssm from "@aws-sdk/client-ssm";
import * as node_cfn from "@functionless/formation";
import { App, CfnOutput, Stack } from "aws-cdk-lib";
import { ArnPrincipal, Role } from "aws-cdk-lib/aws-iam";
import { SdkProvider } from "aws-cdk/lib/api/aws-auth";
import { CloudFormationDeployments } from "aws-cdk/lib/api/cloudformation-deployments";
import { DeployStackResult } from "aws-cdk/lib/api/deploy-stack";
// eslint-disable-next-line import/no-extraneous-dependencies
import AWS, {
DynamoDB,
Expand All @@ -27,6 +30,7 @@ export interface RuntimeTestExecutionContext {
selfDestructProps: SelfDestructorProps;
stackRetentionPolicy: "RETAIN" | "DELETE" | "SELF_DESTRUCT";
deployTarget: "AWS" | "LOCALSTACK";
deployer: "CFN" | "NODE_CFN";
cleanUpStack: boolean;
}

Expand All @@ -52,6 +56,7 @@ export const runtimeTestExecutionContext: RuntimeTestExecutionContext = {
: "SELF_DESTRUCT")) as RuntimeTestExecutionContext["stackRetentionPolicy"],
// AWS | LOCALSTACK ; default: LOCALSTACK
deployTarget: deploymentTarget as RuntimeTestExecutionContext["deployTarget"],
deployer: (process.env.TEST_DEPLOYER as "CFN" | "NODE_CFN") ?? "CFN",
cleanUpStack: process.env.CLEAN_UP_STACK === "1" ? true : false,
};

Expand Down Expand Up @@ -288,6 +293,9 @@ export function runtimeTestSuite<
>)
| undefined = undefined;

let synthTime: number = 0;
let deploymentTime: number = 0;

beforeAll(async () => {
// resolve account and arn of current credentials
const caller = await sts.getCallerIdentity().promise();
Expand Down Expand Up @@ -321,25 +329,40 @@ export function runtimeTestSuite<
(t) => ("error" in t && t.error) || ("skip" in t && t.skip)
);
if (!allErrored) {
const startSynth = new Date();
const cloudAssembly = await asyncSynth(app);
synthTime = new Date().getTime() - startSynth.getTime();
const assetManifestArtifact = cloudAssembly.tryGetArtifact(
`${stack.artifactId}.assets`
) as unknown as cxapi.AssetManifestArtifact;
stackArtifact = cloudAssembly.getStackArtifact(
stack.artifactId
) as unknown as cxapi.CloudFormationStackArtifact;

// Inspiration for the current approach: https://github.com/aws/aws-cdk/pull/18667#issuecomment-1075348390
// Writeup on performance improvements: https://github.com/functionless/functionless/pull/184#issuecomment-1144767427
const deployOut = await getCfnClient().then((client) =>
client.deployStack({
stack: stackArtifact!,
tags: Object.entries(stack.tags.tagValues()).map(([k, v]) => ({
Key: k,
Value: v,
})),
// hotswap uses the current user's role and not the bootstrapped role.
// the CI user does not have all of the right permissions.
hotswap: !process.env.CI,
})
);
const startDeploy = new Date();

let deployOut: DeployStackResult | node_cfn.StackState;
if (runtimeTestExecutionContext.deployer === "CFN") {
// Inspiration for the current approach: https://github.com/aws/aws-cdk/pull/18667#issuecomment-1075348390
// Writeup on performance improvements: https://github.com/functionless/functionless/pull/184#issuecomment-1144767427
deployOut = await getCfnClient().then((client) =>
client.deployStack({
stack: stackArtifact!,
tags: Object.entries(stack.tags.tagValues()).map(([k, v]) => ({
Key: k,
Value: v,
})),
// hotswap uses the current user's role and not the bootstrapped role.
// the CI user does not have all of the right permissions.
hotswap: !process.env.CI,
})
);
} else {
deployOut = await formationDeploy(stackArtifact, assetManifestArtifact);
}
deploymentTime = new Date().getTime() - startDeploy.getTime();

console.log(deployOut.outputs);

const testRoleArn =
deployOut.outputs[stack.resolve(testArnOutput.logicalId)];
Expand Down Expand Up @@ -385,18 +408,46 @@ export function runtimeTestSuite<
deployOutputs: s,
}));
}

async function formationDeploy(
stackArtifact: cxapi.CloudFormationStackArtifact,
assetManifest: cxapi.AssetManifestArtifact
) {
const caller = await sts.getCallerIdentity().promise();
console.log(JSON.stringify(stackArtifact.template, null, 2));
const stack = new node_cfn.Stack({
account: caller.Account!,
region: clientConfig.region!,
stackName: stackArtifact.stackName,
// @ts-ignore
ssmClient: new ssm.SSMClient({
credentials: clientConfig.credentials!,
region: clientConfig.region!,
}),
sdkConfig: clientConfig,
});

const result = await stack.updateStack(
stackArtifact.template,
undefined,
assetManifest.file
);

return result;
}
});

afterAll(async () => {
console.log("Synth Time:", synthTime, "DeployTime:", deploymentTime);
if (
stackArtifact &&
runtimeTestExecutionContext.stackRetentionPolicy === "DELETE"
) {
await getCfnClient().then((client) =>
client.destroyStack({
stack: stackArtifact!,
})
);
// await getCfnClient().then((client) =>
// client.destroyStack({
// stack: stackArtifact!,
// })
// );
}
});

Expand Down
10 changes: 9 additions & 1 deletion packages/@functionless/aws-constructs/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@
"types": ["node"]
},
"include": ["src/**/*.ts", "src/**/*.json"],
"exclude": []
"exclude": [],
"references": [
{
"path": "../formation"
},
{
"path": "../ast"
}
]
}
Loading