Skip to content

Commit

Permalink
23 adding localstack cfg, docker-compose.yml and aws library wrapper (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ed-snodgrass authored Dec 18, 2023
1 parent dc1f58a commit 4d209fb
Show file tree
Hide file tree
Showing 6 changed files with 578 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,5 @@ dist
# Terraform cache
terraform/.terraform
.tool-versions

localstack/volume
4 changes: 4 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
"version": "0.0.0",
"private": true,
"dependencies": {
"@aws-sdk/client-s3": "^3.472.0",
"@aws-sdk/client-ses": "^3.470.0",
"@aws-sdk/client-sqs": "^3.470.0",
"@aws-sdk/client-ssm": "^3.462.0",
"@aws-sdk/rds-signer": "^3.462.0",
"@aws-sdk/s3-request-presigner": "^3.472.0",
"@opentelemetry/instrumentation": "^0.45.1",
"@prisma/instrumentation": "^5.7.0",
"@redwoodjs/api": "6.4.2",
Expand Down
106 changes: 106 additions & 0 deletions api/src/lib/aws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import {
GetObjectCommand,
PutObjectCommand,
PutObjectCommandInput,
S3Client,
} from '@aws-sdk/client-s3'
import {ReceiveMessageCommand, SendMessageCommand, SQSClient} from '@aws-sdk/client-sqs'
import {getSignedUrl as awsGetSignedUrl} from '@aws-sdk/s3-request-presigner'

function getS3Client() {
let s3: S3Client;
if (process.env.LOCALSTACK_HOSTNAME) {
/*
1. Make sure the local environment has awslocal installed.
2. Use the commands to create a bucket to test with.
- awslocal s3api create-bucket --bucket arpa-audit-reports --region us-west-2 --create-bucket-configuration '{"LocationConstraint": "us-west-2"}'
3. Access bucket resource metadata through the following URL.
- awslocal s3api list-buckets
- awslocal s3api list-objects --bucket arpa-audit-reports
*/
console.log('------------ USING LOCALSTACK ------------');
const endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:${process.env.EDGE_PORT || 4566}`;
console.log(`endpoint: ${endpoint}`);
s3 = new S3Client({
endpoint,
forcePathStyle: true,
region: process.env.AWS_DEFAULT_REGION,
});
} else {
s3 = new S3Client();
}
return s3;
}

async function sendPutObjectToS3Bucket(bucketName: string, key: string, body: any) {
const s3 = getS3Client();
const uploadParams : PutObjectCommandInput = {
Bucket: bucketName,
Key: key,
Body: body,
ServerSideEncryption: 'AES256',
};
await s3.send(new PutObjectCommand(uploadParams));
}

async function sendHeadObjectToS3Bucket(bucketName: string, key: string) {
const s3 = getS3Client();
const uploadParams : PutObjectCommandInput = {
Bucket: bucketName,
Key: key,
};
await s3.send(new PutObjectCommand(uploadParams));
}

/**
* This function is a wrapper around the getSignedUrl function from the @aws-sdk/s3-request-presigner package.
* Exists to organize the imports and to make it easier to mock in tests.
*/
async function getSignedUrl(bucketName: string, key: string) {
const s3 = getS3Client();
const baseParams = { Bucket: bucketName, Key: key };
return awsGetSignedUrl(s3, new GetObjectCommand(baseParams), { expiresIn: 60 });
}

function getSQSClient() {
let sqs: SQSClient;
if (process.env.LOCALSTACK_HOSTNAME) {
console.log('------------ USING LOCALSTACK FOR SQS ------------');
const endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:${process.env.EDGE_PORT || 4566}`;
sqs = new SQSClient({ endpoint, region: process.env.AWS_DEFAULT_REGION });
} else {
sqs = new SQSClient();
}
return sqs;
}

async function sendSqsMessage(queueUrl: string, messageBody: any) {
const sqs = getSQSClient();
await sqs.send(new SendMessageCommand({
QueueUrl: queueUrl,
MessageBody: JSON.stringify(messageBody),
}));
}

async function receiveSqsMessage(queueUrl: string) {
const sqs = getSQSClient();
// const receiveResp = await sqs.send(new ReceiveMessageCommand({
// QueueUrl: process.env.TASK_QUEUE_URL, WaitTimeSeconds: 20, MaxNumberOfMessages: 1,
// }));

// const receiveResp = await sqs.send(new ReceiveMessageCommand({
// QueueUrl: process.env.TASK_QUEUE_URL, WaitTimeSeconds: 20, MaxNumberOfMessages: 1,
// }));

await sqs.send(new ReceiveMessageCommand({
QueueUrl: queueUrl, WaitTimeSeconds: 20, MaxNumberOfMessages: 1,
}));
}

export default {
sendPutObjectToS3Bucket,
sendHeadObjectToS3Bucket,
getSignedUrl,
sendSqsMessage,
receiveSqsMessage,
};
17 changes: 17 additions & 0 deletions localstack/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: "3.8"

services:
localstack:
container_name: "cpf-reporter-localstack-main"
image: localstack/localstack
ports:
- "4566:4566" # LocalStack Gateway
- "4510-4559:4510-4559" # external services port range
environment:
- DEBUG=${DEBUG-}
- DOCKER_HOST=unix:///var/run/docker.sock
- AWS_DEFAULT_REGION=${AWS_REGION:-us-west-2}
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
- "./entrypoint/init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh"
16 changes: 16 additions & 0 deletions localstack/entrypoint/init-aws.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#! /bin/bash

export AWS_ACCESS_KEY_ID="test"
export AWS_SECRET_ACCESS_KEY="test"

VALID_EMAILS=(
"[email protected]"
)

for email in "${VALID_EMAILS[@]}"; do
awslocal ses verify-email-identity --email-address ${email}
echo "Verified ${email} to send with localstack SES"
done

awslocal s3api create-bucket --bucket cpf-reporter --region us-west-2 --create-bucket-configuration '{"LocationConstraint": "us-west-2"}'

Loading

0 comments on commit 4d209fb

Please sign in to comment.