Skip to content

Commit

Permalink
Review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
flostadler committed Nov 8, 2024
1 parent 5a9d152 commit 8496d7d
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 38 deletions.
56 changes: 26 additions & 30 deletions examples/cfn-custom-resource/ami-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,57 +8,53 @@ var archToAMINamePattern = {
"HVM64": "al2023-ami-2023.*-kernel-*-x86_64",
"HVMG2": "amzn-ami-graphics-hvm*x86_64-ebs*"
};
var aws = require("aws-sdk");
exports.handler = function(event, context) {

console.log("REQUEST RECEIVED:\n" + JSON.stringify(event));
const { EC2Client, DescribeImagesCommand } = require("@aws-sdk/client-ec2");

exports.handler = async function(event, context) {
const redactedEvent = { ...event, ResponseURL: "REDACTED" };
console.log("REQUEST RECEIVED:\n" + JSON.stringify(redactedEvent));

// For Delete requests, immediately send a SUCCESS response.
if (event.RequestType == "Delete") {
sendResponse(event, context, "SUCCESS");
await sendResponse(event, context, "SUCCESS");
return;
}

var responseStatus = "FAILED";
var responseData = {};

var ec2 = new aws.EC2({region: event.ResourceProperties.Region});
var describeImagesParams = {
const ec2Client = new EC2Client({ region: event.ResourceProperties.Region });
const describeImagesParams = {
Filters: [{ Name: "name", Values: [archToAMINamePattern[event.ResourceProperties.Architecture]]}],
Owners: [event.ResourceProperties.Architecture == "HVMG2" ? "679593333241" : "amazon"]
};

// Get AMI IDs with the specified name pattern and owner
ec2.describeImages(describeImagesParams, function(err, describeImagesResult) {
if (err) {
responseData = {Error: "DescribeImages call failed"};
console.log(responseData.Error + ":\n", err);
try {
const describeImagesResult = await ec2Client.send(new DescribeImagesCommand(describeImagesParams));
var images = describeImagesResult.Images;
// Sort images by name in descending order. The names contain the AMI version, formatted as YYYY.MM.Ver.
images.sort((x, y) => y.Name.localeCompare(x.Name));
for (var j = 0; j < images.length; j++) {
if (isBeta(images[j].Name)) continue;
responseStatus = "SUCCESS";
responseData["Id"] = images[j].ImageId;
break;
}
else {
var images = describeImagesResult.Images;
// Sort images by name in decscending order. The names contain the AMI version, formatted as YYYY.MM.Ver.
images.sort(function(x, y) { return y.Name.localeCompare(x.Name); });
for (var j = 0; j < images.length; j++) {
if (isBeta(images[j].Name)) continue;
responseStatus = "SUCCESS";
responseData["Id"] = images[j].ImageId;
break;
}
}
sendResponse(event, context, responseStatus, responseData);
});
} catch (err) {
responseData = { Error: "DescribeImages call failed" };
console.log(responseData.Error + ":\n", err);
}

await sendResponse(event, context, responseStatus, responseData);
};

// Check if the image is a beta or rc image. The Lambda function won't return any of those images.
function isBeta(imageName) {
return imageName.toLowerCase().indexOf("beta") > -1 || imageName.toLowerCase().indexOf(".rc") > -1;
}


// Send response to the pre-signed S3 URL
function sendResponse(event, context, responseStatus, responseData) {

async function sendResponse(event, context, responseStatus, responseData) {
var responseBody = JSON.stringify({
Status: responseStatus,
Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
Expand Down Expand Up @@ -104,4 +100,4 @@ function sendResponse(event, context, responseStatus, responseData) {
// write data to request body
request.write(responseBody);
request.end();
}
}
4 changes: 2 additions & 2 deletions examples/cfn-custom-resource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const rpa2 = new awsClassic.iam.RolePolicyAttachment("lambdaRolePolicyAttachment
policyArn: awsClassic.iam.ManagedPolicies.AWSLambdaBasicExecutionRole,
});

const bucket = new awsClassic.s3.Bucket('custom-resource-emulator', {
const bucket = new awsClassic.s3.BucketV2('custom-resource-emulator', {
forceDestroy: true,
});

Expand All @@ -46,7 +46,7 @@ const handlerCode = new awsClassic.s3.BucketObjectv2("handler-code", {

// Create the Lambda function for the custom resource
const lambdaFunction = new awsClassic.lambda.Function("ami-lookup-custom-resource", {
runtime: awsClassic.types.enums.lambda.Runtime.NodeJS16dX,
runtime: awsClassic.types.enums.lambda.Runtime.NodeJS20dX,
s3Bucket: bucket.bucket,
s3Key: handlerCode.key,
handler: "index.handler",
Expand Down
5 changes: 4 additions & 1 deletion examples/examples_nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@ func TestCustomResourceEmulator(t *testing.T) {
test := pulumitest.NewPulumiTest(t, filepath.Join(cwd, "cfn-custom-resource"), options...)
test.SetConfig(t, "amiRegion", "us-west-2")

previewResult := test.Preview(t)
t.Logf("#%v", previewResult.ChangeSummary)

upResult := test.Up(t)
t.Logf("#%v", upResult.Summary)
crossTest(t, upResult.Outputs)

previewResult := test.Preview(t)
previewResult = test.Preview(t)
assertpreview.HasNoChanges(t, previewResult)

test.SetConfig(t, "amiRegion", "us-east-1")
Expand Down
2 changes: 1 addition & 1 deletion provider/cmd/pulumi-resource-aws-native/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -181222,7 +181222,7 @@
]
},
"aws-native:cloudformation:CustomResourceEmulator": {
"description": "The Custom Resource Emulator allows you to use AWS CloudFormation Custom Resources directly in your Pulumi programs. It provides a way to invoke AWS Lambda functions that implement custom provisioning logic following the CloudFormation Custom Resource protocol.\n\n\u003e **Note**: Currently, only Lambda-backed Custom Resources are supported. SNS-backed Custom Resources are not supported at this time.\n\n## Example Usage\n\n```typescript\nimport * as aws from \"@pulumi/aws-native\";\n\nconst bucket = new aws.s3.Bucket('custom-resource-emulator');\n\n// Create a Custom Resource that invokes a Lambda function\nconst cr = new aws.cloudformation.CustomResourceEmulator('cr', {\n bucketName: bucket.id,\n bucketKeyPrefix: 'custom-resource-emulator',\n customResourceProperties: {\n hello: \"world\"\n },\n serviceToken: \"arn:aws:lambda:us-west-2:123456789012:function:my-custom-resource\",\n resourceType: 'Custom::MyResource',\n}, { customTimeouts: { create: '5m', update: '5m', delete: '5m' } });\n\n// Access the response data\nexport const customResourceData = customResource.data;\n```\n\n## About CloudFormation Custom Resources\n\nCloudFormation Custom Resources allow you to write custom provisioning logic for resources that aren't directly available as AWS CloudFormation resource types. Common use cases include:\n\n- Managing resources outside of AWS (e.g., GitHub repositories, external APIs)\n- Implementing complex provisioning logic\n- Performing custom validations or transformations\n- Integrating with third-party services\n- Implementing organization-specific infrastructure patterns\n\nFor more information about CloudFormation Custom Resources, see [Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html) in the AWS CloudFormation User Guide.\n\n## Permissions\n\nThe IAM principal used by your Pulumi program must have the following permissions:\n\n1. `lambda:InvokeFunction` on the Lambda function specified in `serviceToken`\n2. S3 permissions on the bucket specified in `bucketName`:\n - `s3:PutObject`\n - `s3:GetObject`\n - `s3:HeadObject`\n\n## Lambda Function Requirements\n\nThe Lambda function specified in `serviceToken` must implement the CloudFormation Custom Resource lifecycle.\nFor detailed information about implementing Lambda-backed Custom Resources, see [AWS Lambda-backed Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html) in the AWS CloudFormation User Guide.\n\n## Timeouts\n\nCustom Resources have a default timeout of 60 minutes, matching the CloudFormation timeout for custom resource operations. You can customize it using the [`customTimeouts`](https://www.pulumi.com/docs/iac/concepts/options/customtimeouts/) resource option.\n",
"description": "The Custom Resource Emulator allows you to use AWS CloudFormation Custom Resources directly in your Pulumi programs. It provides a way to invoke AWS Lambda functions that implement custom provisioning logic following the CloudFormation Custom Resource protocol.\n\n\u003e **Note**: Currently, only Lambda-backed Custom Resources are supported. SNS-backed Custom Resources are not supported at this time.\n\n## Example Usage\n\n```typescript\nimport * as aws from \"@pulumi/aws-native\";\n\nconst bucket = new aws.s3.Bucket('custom-resource-emulator');\n\n// Create a Custom Resource that invokes a Lambda function\nconst cr = new aws.cloudformation.CustomResourceEmulator('cr', {\n bucketName: bucket.id,\n bucketKeyPrefix: 'custom-resource-emulator',\n customResourceProperties: {\n hello: \"world\"\n },\n serviceToken: \"arn:aws:lambda:us-west-2:123456789012:function:my-custom-resource\",\n resourceType: 'Custom::MyResource',\n}, { customTimeouts: { create: '5m', update: '5m', delete: '5m' } });\n\n// Access the response data\nexport const customResourceData = customResource.data;\n```\n\n## About CloudFormation Custom Resources\n\nCloudFormation Custom Resources allow you to write custom provisioning logic for resources that aren't directly available as AWS CloudFormation resource types. Common use cases include:\n\n- Implementing complex provisioning logic\n- Performing custom validations or transformations\n- Integrating with third-party services\n- Implementing organization-specific infrastructure patterns\n\nFor more information about CloudFormation Custom Resources, see [Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html) in the AWS CloudFormation User Guide.\n\n## Permissions\n\nThe IAM principal used by your Pulumi program must have the following permissions:\n\n1. `lambda:InvokeFunction` on the Lambda function specified in `serviceToken`\n2. S3 permissions on the bucket specified in `bucketName`:\n - `s3:PutObject`\n - `s3:GetObject`\n - `s3:HeadObject`\n\n## Lambda Function Requirements\n\nThe Lambda function specified in `serviceToken` must implement the CloudFormation Custom Resource lifecycle.\nFor detailed information about implementing Lambda-backed Custom Resources, see [AWS Lambda-backed Custom Resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html) in the AWS CloudFormation User Guide.\n\n## Timeouts\n\nCustom Resources have a default timeout of 60 minutes, matching the CloudFormation timeout for custom resource operations. You can customize it using the [`customTimeouts`](https://www.pulumi.com/docs/iac/concepts/options/customtimeouts/) resource option.\n",
"properties": {
"bucket": {
"type": "string",
Expand Down
1 change: 0 additions & 1 deletion provider/pkg/schema/docs/content/cfn-custom-resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export const customResourceData = customResource.data;

CloudFormation Custom Resources allow you to write custom provisioning logic for resources that aren't directly available as AWS CloudFormation resource types. Common use cases include:

- Managing resources outside of AWS (e.g., GitHub repositories, external APIs)
- Implementing complex provisioning logic
- Performing custom validations or transformations
- Integrating with third-party services
Expand Down
1 change: 0 additions & 1 deletion sdk/dotnet/CloudFormation/CustomResourceEmulator.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion sdk/go/aws/cloudformation/customResourceEmulator.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion sdk/nodejs/cloudformation/customResourceEmulator.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8496d7d

Please sign in to comment.