diff --git a/demos/community-day/.gitignore b/demos/community-day/.gitignore new file mode 100644 index 0000000..c4f68a5 --- /dev/null +++ b/demos/community-day/.gitignore @@ -0,0 +1,4 @@ +cdk.tf.json +cdk.tf +assets/ +tcons-staging/ diff --git a/demos/community-day/.prettierignore b/demos/community-day/.prettierignore new file mode 100644 index 0000000..6cbd0c4 --- /dev/null +++ b/demos/community-day/.prettierignore @@ -0,0 +1,5 @@ +# ignore fogg managed files +.fogg-component.yaml +package.json +src/index.ts +src/.gen/**/* diff --git a/demos/community-day/.prettierrc.json b/demos/community-day/.prettierrc.json new file mode 100644 index 0000000..e3dc183 --- /dev/null +++ b/demos/community-day/.prettierrc.json @@ -0,0 +1,17 @@ +{ + "semi": true, + "singleQuote": false, + "trailingComma": "es5", + "tabWidth": 2, + "useTabs": false, + "printWidth": 70, + "endOfLine": "lf", + "arrowParens": "avoid", + "bracketSpacing": true, + "bracketSameLine": false, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "requirePragma": false, + "proseWrap": "preserve", + "quoteProps": "as-needed" +} \ No newline at end of file diff --git a/demos/community-day/cdktf.json b/demos/community-day/cdktf.json new file mode 100644 index 0000000..0601d90 --- /dev/null +++ b/demos/community-day/cdktf.json @@ -0,0 +1,8 @@ +{ + "language": "typescript", + "codeMakerOutput": "src/.gen", + "app": "pnpm ts-node --swc -P ./tsconfig.json src/index.ts", + "terraformProviders": [], + "terraformModules": [], + "projectId": "d1dd24b3-6056-4263-93ae-ec59454a47b5" +} diff --git a/demos/community-day/lambda/hello.js b/demos/community-day/lambda/hello.js new file mode 100644 index 0000000..4798bcc --- /dev/null +++ b/demos/community-day/lambda/hello.js @@ -0,0 +1,32 @@ +const { SNSClient, PublishCommand } = require("@aws-sdk/client-sns"); + +const snsClient = new SNSClient({}); + +exports.handler = async function (event) { + console.log("request:", JSON.stringify(event, undefined, 2)); + + const params = { + Message: JSON.stringify({ + message: "Processing event from EventBridge", + eventDetail: event.detail, + }), + TopicArn: process.env.SNS_TOPIC_ARN, + }; + + try { + const command = new PublishCommand(params); + const data = await snsClient.send(command); + console.log(`Message sent to the topic ${params.TopicArn}`); + console.log("MessageID is " + data.MessageId); + return { + statusCode: 200, + body: JSON.stringify({ + message: "Message published successfully", + messageId: data.MessageId, + }), + }; + } catch (err) { + console.error("Error publishing to SNS:", err); + throw err; + } +}; diff --git a/demos/community-day/package.json b/demos/community-day/package.json new file mode 100644 index 0000000..cf38349 --- /dev/null +++ b/demos/community-day/package.json @@ -0,0 +1,32 @@ +{ + "name": "community-day", + "version": "1.0.0", + "main": "src/main.js", + "types": "src/main.ts", + "license": "MPL-2.0", + "private": true, + "scripts": { + "synth": "ts-node --swc -P ./tsconfig.json src/index.ts", + "prettier": "prettier --write ." + }, + "engines": { + "node": ">=20.9" + }, + "dependencies": { + "@cdktf/provider-cloudinit": "^11.0.0", + "@tcons/provider-tconsaws": "0.0.1", + "cdktf": "^0.21.0", + "constructs": "^10.4.2", + "terraconstructs": "^0.1.3" + }, + "devDependencies": { + "@swc/core": "^1.10.12", + "@types/jest": "^30.0.0", + "@types/node": "^24.0.14", + "jest": "^30.0.4", + "prettier": "^3.4.2", + "ts-jest": "^29.4.0", + "ts-node": "^10.9.2", + "typescript": "^5.8.3" + } +} \ No newline at end of file diff --git a/demos/community-day/src/index.ts b/demos/community-day/src/index.ts new file mode 100644 index 0000000..e9c83f9 --- /dev/null +++ b/demos/community-day/src/index.ts @@ -0,0 +1,39 @@ +import * as fs from "node:fs"; +import * as path from "node:path"; +import { App, } from "cdktf/lib/app"; +import { CloudinitProvider } from "@cdktf/provider-cloudinit/lib/provider"; +import { provider } from "@tcons/provider-tconsaws"; +import { Testing } from "cdktf/lib/testing"; +import { CdkWorkshopStack } from "./stack"; +import { execSync } from "node:child_process"; + +const outdir = "cdktf.out"; +const app = Testing.app({ + outdir, +}); +const stack = new CdkWorkshopStack(app, "Default", { + environmentName: "demo", + providerConfig: { + region: "us-east-1", + }, + gridUUID: "demo-uuid", +}); +new CloudinitProvider(stack, "CloudInit"); + +const resultString = Testing.synth(stack); +fs.writeFileSync("cdk.tf.json", resultString); + + +const resultHclString = Testing.synthHcl(stack); +fs.writeFileSync("cdk.tf", resultHclString); +execSync("terraform fmt cdk.tf") + +// // Copy the generated Terraform code to the current directory to keep relative directory references +// app.synth(); +// const stackSynthDir = path.join(outdir, app.manifest.forStack(stack).workingDirectory); + +// fs.cpSync(stackSynthDir, ".", { recursive: true }); +// fs.rmSync(outdir, { recursive: true }); +// if (process.env.CI) { +// fs.renameSync("cdk.tf.json", "ci-cdk.tf.json"); +// } diff --git a/demos/community-day/src/stack.ts b/demos/community-day/src/stack.ts new file mode 100644 index 0000000..805afe4 --- /dev/null +++ b/demos/community-day/src/stack.ts @@ -0,0 +1,100 @@ +// https://github.com/TerraConstructs/base/blob/integ-feat-signal-poc/integ/aws/compute/apps/instance.ts +import { signal } from "@tcons/provider-tconsaws"; +import { Construct } from "constructs"; +import { AwsStack, AwsStackProps } from "terraconstructs/lib/aws"; +import { + Vpc, + Instance, + InstanceType, + InstanceClass, + InstanceSize, + AmazonLinuxImage, + AmazonLinuxGeneration, + InstanceInitiatedShutdownBehavior, + Port, + Code, + LambdaFunction, + Runtime, + SecurityGroup, + Schedule, +} from "terraconstructs/lib/aws/compute"; +import { Queue } from "terraconstructs/lib/aws/notify"; +import { SqsSubscription } from "terraconstructs/lib/aws/notify/subscriptions"; +import { + Rule, + IRuleTarget, + Topic, +} from "terraconstructs/lib/aws/notify"; +import { + Bucket, + BucketEncryption, +} from "terraconstructs/lib/aws/storage"; + +export class CdkWorkshopStack extends AwsStack { + constructor(scope: Construct, id: string, props: AwsStackProps) { + super(scope, id, props); + + const vpc = new Vpc(this, "VPC"); + + const lambda = new LambdaFunction(this, "LambdaFunction", { + runtime: Runtime.NODEJS_22_X, + code: Code.fromAsset("lambda"), + handler: "hello.handler", + }); + + const lambdaTarget: IRuleTarget = { + bind: () => ({ + arn: lambda.functionArn, + targetResource: lambda, + }), + }; + + // Event bridge schedule and rule for SGX AR report processor lambda execution + new Rule(this, "Rule", { + ruleName: `schedule-rule`, + schedule: Schedule.cron({ + minute: "10/30", + hour: "*", + day: "*", + month: "*", + year: "*", + }), + targets: [lambdaTarget], + }); + + const topic = new Topic(this, "Topic"); + const queue = new Queue(this, "Queue"); + topic.addSubscription(new SqsSubscription(queue)); + + const instance = new Instance(this, "Instance", { + vpc, + instanceType: InstanceType.of( + InstanceClass.T3, + InstanceSize.NANO + ), + machineImage: new AmazonLinuxImage({ + generation: AmazonLinuxGeneration.AMAZON_LINUX_2, + }), + detailedMonitoring: true, + instanceInitiatedShutdownBehavior: + InstanceInitiatedShutdownBehavior.TERMINATE, + }); + queue.grantConsumeMessages(instance); + + const rdsDbSecurityGroupId = SecurityGroup.fromSecurityGroupId( + this, + "RdsSecurityGroupId", + "sg-0123456789abcdef0" + ); + rdsDbSecurityGroupId.connections.allowFrom( + instance, + Port.MSSQL, + "Allow MySQL access from EC2 instance" + ); + + const bucket = new Bucket(this, "Bucket", { + encryption: BucketEncryption.S3_MANAGED, + }); + bucket.grantReadWrite(instance); + } +} diff --git a/demos/community-day/tsconfig.json b/demos/community-day/tsconfig.json new file mode 100644 index 0000000..c60f677 --- /dev/null +++ b/demos/community-day/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "outDir": "dist", + "declaration": true, + "declarationMap": true, + "experimentalDecorators": true, + "sourceMap": true, + "inlineSources": true, + "lib": ["es2023"], + "module": "node16", + "target": "es2022", + "moduleResolution": "node16", + "moduleDetection": "force", + "esModuleInterop": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "strict": true, + "alwaysStrict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "stripInternal": true, + "noEmitOnError": false, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "isolatedDeclarations": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "preserveWatchOutput": true + }, + "include": ["src/**/*.ts"], + "exclude": ["dist", "node_modules", "cdktf.out"] +} diff --git a/index.html b/index.html index 42b2124..bc4db3d 100644 --- a/index.html +++ b/index.html @@ -699,6 +699,16 @@

EC2 Instance with CFN Signal +
  • + +
  • @@ -1331,7 +1341,7 @@

    - The + The terraform-provider-aws aria-controls="faq-10" > How does TerraConstructs compare to How does TerraConstructs compare to + cdktf-aws-cdk?cdktf-aws-cdk? API concepts inside a single resource, while Terraform models them as separate resources with distinct lifecycles and dependencies. The result can be incomplete - mappings, unstable plans, and missing features (such as the asset pipeline). - TerraConstructs re-implements the AWS CDK - L2 behaviors on top of + mappings, unstable plans, and missing features (such as the + asset pipeline). TerraConstructs re-implements the AWS CDK L2 + behaviors on top of provider-aws