-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1c4a7b6
commit 3fc1abc
Showing
8 changed files
with
969 additions
and
955 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
import { modulate, config, Provider, Terraform } from '../src/config' | ||
import { AWS05200 as AWS } from '../registry/index' | ||
|
||
import { rout53_zone, acm_cert, route53_record, acm_validation } from './route53' | ||
|
||
// ,e, | ||
// /~~~8e 888-~88e " | ||
// 88b 888 888b 888 | ||
// e88~-888 888 8888 888 | ||
// C888 888 888 888P 888 | ||
// "88_-888 888-_88" 888 | ||
// 888 | ||
const api_domain = ({ subdomain = 'api', apex = 'chopshop-test.net', cert_arn }): AWS => ({ | ||
resource: { | ||
apigatewayv2_domain_name: { | ||
domain_name: `${subdomain}.${apex}`, | ||
/** | ||
* Block type "domain_name_configuration" is represented by a list | ||
* of objects, so it must be indexed using a numeric key, like | ||
* .domain_name_configuration[0] | ||
*/ | ||
// @ts-ignore | ||
domain_name_configuration: [ | ||
{ | ||
certificate_arn: cert_arn, | ||
endpoint_type: 'REGIONAL', | ||
security_policy: 'TLS_1_2', | ||
target_domain_name: '-->', | ||
hosted_zone_id: '-->', | ||
}, | ||
], | ||
tags: { | ||
Name: `${subdomain}.${apex}`, | ||
BroughtToYouBy: '@-0/micro', | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
const api_gateway = ({ name }): AWS => ({ | ||
resource: { | ||
apigatewayv2_api: { | ||
name, | ||
description: `api for ${name}`, | ||
disable_execute_api_endpoint: false, | ||
protocol_type: 'HTTP', | ||
cors_configuration: { | ||
allow_headers: [ | ||
'content-type', | ||
'x-amz-date', | ||
'authorization', | ||
'x-api-key', | ||
'x-amz-security-token', | ||
'x-amz-user-agent', | ||
], | ||
allow_methods: ['*'], | ||
allow_origins: ['*'], | ||
max_age: 300, | ||
}, | ||
api_endpoint: '-->', | ||
execution_arn: '-->', | ||
id: '-->', | ||
}, | ||
}, | ||
}) | ||
|
||
const api_stage = ({ api_id, name = '$default' }): AWS => ({ | ||
resource: { | ||
apigatewayv2_stage: { | ||
api_id, | ||
name, | ||
auto_deploy: true, | ||
description: `stage ${name} API`, | ||
}, | ||
}, | ||
}) | ||
|
||
const api_lambda_integration = ({ api_id, lambda_invoke_arn }): AWS => ({ | ||
resource: { | ||
// @ts-ignore: 🐛 [3] | ||
apigatewayv2_integration: { | ||
api_id, | ||
integration_uri: lambda_invoke_arn, | ||
integration_type: 'AWS_PROXY', | ||
integration_method: 'POST', | ||
connection_type: 'INTERNET', | ||
payload_format_version: '2.0', | ||
timeout_milliseconds: 29000, // 30 sec max for HTTP, 29 for WebSockets | ||
id: '-->', | ||
}, | ||
}, | ||
}) | ||
|
||
const api_route = ({ api_id, route_key = 'ANY /', integration_id }): AWS => ({ | ||
resource: { | ||
// @ts-ignore: 🐛 [2] | ||
apigatewayv2_route: { | ||
api_id, | ||
route_key, | ||
target: `integrations/${integration_id}`, | ||
id: '-->', | ||
|
||
//authorization_scopes: 'TODO', | ||
//authorization_type: 'TODO', | ||
//authorizer_id: 'TODO' | ||
}, | ||
}, | ||
}) | ||
|
||
interface Subdomains { | ||
[key: string]: { | ||
[key: string]: { | ||
invoke_arn: string | ||
} | ||
} | ||
} | ||
// 888 888 /~~88b | ||
// 888-~88e-~88e e88~-_ e88~\888 888 888 888 e88~~8e | 888 | ||
// 888 888 888 d888 i d888 888 888 888 888 d888 88b ` d88P | ||
// 888 888 888 8888 | 8888 888 888 888 888 8888__888 d88P | ||
// 888 888 888 Y888 ' Y888 888 888 888 888 Y888 , d88P | ||
// 888 888 888 "88_-~ "88_/888 "88_-888 888 "88___/ d88P___ | ||
|
||
/** | ||
* subdomains module | ||
* | ||
* @param apex - apex domain name | ||
* @param subdomains - array of subdomains | ||
* - name - name of the subdomain | ||
* - lambda_integration - lambda integration object | ||
* - lambda_invoke_arn - arn of the lambda function to integrate | ||
* - routes - array of routes | ||
* - route object | ||
* - route_key - route key | ||
* - integration_id - id of the integration to use | ||
* @param my - self reference for referencing other resources | ||
* | ||
*/ | ||
export const subdomains = ( | ||
{ | ||
apex = 'chopshop-test.net', | ||
subdomainRoutes = { | ||
test: { | ||
'ANY /': { | ||
invoke_arn: 'lambda_invoke_arn goes here 📌', | ||
}, | ||
}, | ||
}, | ||
}: { | ||
apex: string | ||
subdomainRoutes: Subdomains | ||
}, | ||
my: { [key: string]: AWS } | ||
) => ({ | ||
zone: rout53_zone({ apex }), // 📌 outside module scope? | ||
...Object.entries(subdomainRoutes).reduce( | ||
(a, [sd, routes]) => ({ | ||
...a, | ||
[`cert_${sd}`]: acm_cert({ apex, subdomain: sd }), | ||
[`domain_${sd}`]: api_domain({ | ||
subdomain: sd, | ||
apex, | ||
cert_arn: | ||
my?.[`validation_${sd}`]?.resource?.acm_certificate_validation?.certificate_arn, | ||
}), | ||
[`record_${sd}`]: route53_record({ | ||
route53_zone_id: my?.zone?.data?.route53_zone?.zone_id, | ||
name: sd, | ||
api_domain_name: | ||
my?.[`domain_${sd}`]?.resource?.apigatewayv2_domain_name | ||
?.domain_name_configuration[0]?.target_domain_name, | ||
api_hosted_zone_id: | ||
my?.[`domain_${sd}`]?.resource?.apigatewayv2_domain_name | ||
?.domain_name_configuration[0]?.hosted_zone_id, | ||
}), | ||
[`record_valid_${sd}`]: route53_record({ | ||
route53_zone_id: my?.zone?.data?.route53_zone?.zone_id, | ||
records: [ | ||
my?.[`cert_${sd}`]?.resource?.acm_certificate?.domain_validation_options[0] | ||
?.resource_record_value, | ||
], | ||
name: my?.[`cert_${sd}`]?.resource?.acm_certificate?.domain_validation_options[0] | ||
?.resource_record_name, | ||
type: my?.[`cert_${sd}`]?.resource?.acm_certificate?.domain_validation_options[0] | ||
?.resource_record_type, | ||
}), | ||
[`validation_${sd}`]: acm_validation({ | ||
cert_arn: my?.[`cert_${sd}`]?.resource?.acm_certificate?.arn, | ||
fqdns: [my?.[`record_valid_${sd}`]?.resource?.route53_record?.fqdn], | ||
}), // TODO | ||
[`gateway_${sd}`]: api_gateway({ name: sd }), | ||
[`stage_${sd}`]: api_stage({ | ||
api_id: my?.[`gateway_${sd}`]?.resource?.apigatewayv2_api?.id, | ||
}), | ||
...Object.entries(routes).reduce( | ||
(acc, [route, { invoke_arn }]) => ({ | ||
...acc, | ||
[`integration_${sd}_${route.split(' ')[0]}`]: api_lambda_integration({ | ||
api_id: my?.[`gateway_${sd}`]?.resource?.apigatewayv2_api?.id, | ||
lambda_invoke_arn: invoke_arn, | ||
}), | ||
[`route_${sd}_${route.split(' ')[0]}`]: api_route({ | ||
api_id: my?.[`gateway_${sd}`]?.resource?.apigatewayv2_api?.id, | ||
route_key: route, | ||
integration_id: | ||
my?.[`integration_${sd}_${route.split(' ')[0]}`]?.resource | ||
?.apigatewayv2_integration?.id, | ||
}), | ||
}), | ||
{} | ||
), | ||
}), | ||
{} | ||
), | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { modulate, config, Provider, Terraform } from '../src/config' | ||
import { AWS05200 as AWS } from '../registry/index' | ||
import { lambda } from './lambda' | ||
import { subdomains } from './api' | ||
|
||
const provider: Provider = { | ||
aws: { | ||
region: 'us-east-2', | ||
profile: 'chopshop', | ||
}, | ||
} | ||
|
||
const terraform: Terraform = { | ||
required_providers: { | ||
aws: { | ||
source: 'hashicorp/aws', | ||
version: '5.20.0', | ||
}, | ||
}, | ||
} | ||
|
||
/** | ||
* | ||
* my?.zone?.data?.route53_zone?.zone_id | ||
*/ | ||
|
||
const module = modulate({ ms1: lambda }) | ||
|
||
const [mod_lambda, out_lambda] = module({ name: 'throwaway-test-123' }) | ||
|
||
const functionInvokeArn = out_lambda?.lambda?.resource?.lambda_function?.invoke_arn | ||
|
||
const moduleAPI = modulate({ subdomains }) | ||
|
||
const [mod_api, out_api] = moduleAPI({ | ||
apex: 'chopshop-test.net', | ||
subdomainRoutes: { | ||
test1: { | ||
'ANY /': { | ||
invoke_arn: functionInvokeArn, | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
// ,e, 888 888 | ||
// e88~~\ e88~-_ 888-~88e-~88e 888-~88e " 888 e88~~8e e88~\888 | ||
// d888 d888 i 888 888 888 888 888b 888 888 d888 88b d888 888 | ||
// 8888 8888 | 888 888 888 888 8888 888 888 8888__888 8888 888 | ||
// Y888 Y888 ' 888 888 888 888 888P 888 888 Y888 , Y888 888 | ||
// "88__/ "88_-~ 888 888 888 888-_88" 888 888 "88___/ "88_/888 | ||
// 888 | ||
|
||
JSON.stringify(out_api, null, 4) // | ||
JSON.stringify(mod_api, null, 4) // | ||
|
||
const compiler = config(provider, terraform, 'main.tf.json') | ||
const compiled = compiler(mod_lambda, mod_api) | ||
|
||
JSON.stringify(compiled, null, 4) //? | ||
|
||
/** | ||
* References: | ||
* [1]: https://dev.to/madflanderz/how-to-get-parts-of-an-typescript-interface-3mko | ||
* [2]: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apigatewayv2_route#argument-reference | ||
* [3]: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/apigatewayv2_integration#response_parameters | ||
* [4]: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function#lambda-file-systems | ||
*/ | ||
|
||
// ~~~888~~~ ,88~-_ 888~-_ ,88~-_ | ||
// 888 d888 \ 888 \ d888 \ | ||
// 888 88888 | 888 | 88888 | | ||
// 888 88888 | 888 | 88888 | | ||
// 888 Y888 / 888 / Y888 / | ||
// 888 `88_-~ 888_-~ `88_-~ | ||
|
||
// - add ability to add tags at the module level | ||
// - missing tick_groups - (top three) in route53_record | ||
// - EFSAccessPoint - missing `file_system_arn` (not in docs) | ||
// - resource: { lambda_function: { file_system_config | ||
// - topic: sns_topic(name), // 📌 outside module scope? | ||
// - apigatewayv2_route 🐛 [2] `request_parameter_key` and `required` bug in docs (nested under section without heading) | ||
// - apigatewayv2_integration: 🐛 [3] `status_code` and `mappings` bug in docs (nested under section without heading) | ||
|
||
/** | ||
* Outline of microservice module: | ||
* - s3 | ||
* - bucket | ||
* - sns | ||
* - upstream topic (subscribed to by lambda) | ||
* - downstream topic (published to by lambda) | ||
* - lambda | ||
* - environment variables | ||
* - S3_BUCKET_NAME (for functions that need to read/write to s3) | ||
* - SNS_TOPIC_ARN (downstream topic to publish to sns) | ||
* - sns subscription (upstream topic) | ||
* - filter policy | ||
* - elastic file system (optional) | ||
* - access point | ||
* - mount target | ||
* - api gateway (optional) | ||
* - domain | ||
* - subdomain | ||
* - routes | ||
* - methods | ||
* - required iam permissions | ||
* - lambda | ||
* - s3 | ||
* - read/write | ||
* - sns | ||
* - publish | ||
* - subscribe | ||
* - cloudwatch | ||
* - logs | ||
* - metrics | ||
* - sns | ||
* - lambda (via AllowExecutionFromSNS) | ||
* - api gateway (optional) | ||
* - lambda (via AllowExecutionFromAPIGateway) | ||
*/ |
Oops, something went wrong.