Skip to content

Instantly share code, notes, and snippets.

@ericdmoore
Created August 8, 2019 19:03
Show Gist options
  • Save ericdmoore/42b05b4f1f15fbb52c1e5c63f15cd0be to your computer and use it in GitHub Desktop.
Save ericdmoore/42b05b4f1f15fbb52c1e5c63f15cd0be to your computer and use it in GitHub Desktop.
/**
* To get this list go to:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ask-skill.html
* and run this in the console.
*/
/*
;(async () => {
const sleep = N => {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, N)
})
}
const init = Array.from(
document.querySelectorAll(
'#toc > ul > li.awstoc.opened > ul > li.awstoc.opened > ul > li.awstoc'
)
)
init.forEach(el => el.click())
await sleep(500)
const opened = Array.from(
document.querySelectorAll(
'#toc > ul > li.awstoc.opened > ul > li.awstoc.opened > ul > li.awstoc'
)
)
const AWS_LISTED_TYPES = opened.reduce((p, el) => {
// interate through the middle N
const types = Array.from(el.childNodes[1].childNodes).reduce((p2, c2) => {
return c2.childNodes.length > 0 ? [...p2, c2.childNodes[0].innerText] : [...p2]
}, [])
// close it up before returning
if (el.classList.contains('opened')) {
el.click()
}
return [...p, ...types]
}, [])
console.log(AWS_LISTED_TYPES.map(e => `'${e}'`).join(', '))
})()
*/
// precalcualted list from prior run
// runOn: 2019-08-08 10:53am CST
export const AWS_LISTED_TYPES = [
'Alexa::ASK::Skill',
'AWS::AmazonMQ::Broker',
'AWS::AmazonMQ::Configuration',
'AWS::AmazonMQ::ConfigurationAssociation',
'AWS::Amplify::App',
'AWS::Amplify::Branch',
'AWS::Amplify::Domain',
'AWS::ApiGateway::Account',
'AWS::ApiGateway::ApiKey',
'AWS::ApiGateway::Authorizer',
'AWS::ApiGateway::BasePathMapping',
'AWS::ApiGateway::ClientCertificate',
'AWS::ApiGateway::Deployment',
'AWS::ApiGateway::DocumentationPart',
'AWS::ApiGateway::DocumentationVersion',
'AWS::ApiGateway::DomainName',
'AWS::ApiGateway::GatewayResponse',
'AWS::ApiGateway::Method',
'AWS::ApiGateway::Model',
'AWS::ApiGateway::RequestValidator',
'AWS::ApiGateway::Resource',
'AWS::ApiGateway::RestApi',
'AWS::ApiGateway::Stage',
'AWS::ApiGateway::UsagePlan',
'AWS::ApiGateway::UsagePlanKey',
'AWS::ApiGateway::VpcLink',
'AWS::ApiGatewayV2::Api',
'AWS::ApiGatewayV2::ApiMapping',
'AWS::ApiGatewayV2::Authorizer',
'AWS::ApiGatewayV2::Deployment',
'AWS::ApiGatewayV2::DomainName',
'AWS::ApiGatewayV2::Integration',
'AWS::ApiGatewayV2::IntegrationResponse',
'AWS::ApiGatewayV2::Model',
'AWS::ApiGatewayV2::Route',
'AWS::ApiGatewayV2::RouteResponse',
'AWS::ApiGatewayV2::Stage',
'AWS::ApplicationAutoScaling::ScalableTarget',
'AWS::ApplicationAutoScaling::ScalingPolicy',
'AWS::AppMesh::Mesh',
'AWS::AppMesh::Route',
'AWS::AppMesh::VirtualNode',
'AWS::AppMesh::VirtualRouter',
'AWS::AppMesh::VirtualService',
'AWS::AppStream::DirectoryConfig',
'AWS::AppStream::Fleet',
'AWS::AppStream::ImageBuilder',
'AWS::AppStream::Stack',
'AWS::AppStream::StackFleetAssociation',
'AWS::AppStream::StackUserAssociation',
'AWS::AppStream::User',
'AWS::AppSync::ApiKey',
'AWS::AppSync::DataSource',
'AWS::AppSync::FunctionConfiguration',
'AWS::AppSync::GraphQLApi',
'AWS::AppSync::GraphQLSchema',
'AWS::AppSync::Resolver',
'AWS::Athena::NamedQuery',
'AWS::AutoScalingPlans::ScalingPlan',
'AWS::AutoScaling::AutoScalingGroup',
'AWS::AutoScaling::LaunchConfiguration',
'AWS::AutoScaling::LifecycleHook',
'AWS::AutoScaling::ScalingPolicy',
'AWS::AutoScaling::ScheduledAction',
'AWS::Backup::BackupPlan',
'AWS::Backup::BackupSelection',
'AWS::Backup::BackupVault',
'AWS::Batch::ComputeEnvironment',
'AWS::Batch::JobDefinition',
'AWS::Batch::JobQueue',
'AWS::Budgets::Budget',
'AWS::CertificateManager::Certificate',
'AWS::Cloud9::EnvironmentEC2',
'AWS::CloudFormation::CustomResource',
'AWS::CloudFormation::Macro',
'AWS::CloudFormation::Stack',
'AWS::CloudFormation::WaitCondition',
'AWS::CloudFormation::WaitConditionHandle',
'AWS::CloudFront::CloudFrontOriginAccessIdentity',
'AWS::CloudFront::Distribution',
'AWS::CloudFront::StreamingDistribution',
'AWS::ServiceDiscovery::HttpNamespace',
'AWS::ServiceDiscovery::Instance',
'AWS::ServiceDiscovery::PrivateDnsNamespace',
'AWS::ServiceDiscovery::PublicDnsNamespace',
'AWS::ServiceDiscovery::Service',
'AWS::CloudTrail::Trail',
'AWS::CloudWatch::Alarm',
'AWS::CloudWatch::AnomalyDetector',
'AWS::CloudWatch::Dashboard',
'AWS::Logs::Destination',
'AWS::Logs::LogGroup',
'AWS::Logs::LogStream',
'AWS::Logs::MetricFilter',
'AWS::Logs::SubscriptionFilter',
'AWS::Events::EventBusPolicy',
'AWS::Events::Rule',
'AWS::CodeBuild::Project',
'AWS::CodeCommit::Repository',
'AWS::CodeDeploy::Application',
'AWS::CodeDeploy::DeploymentConfig',
'AWS::CodeDeploy::DeploymentGroup',
'AWS::CodePipeline::CustomActionType',
'AWS::CodePipeline::Pipeline',
'AWS::CodePipeline::Webhook',
'AWS::CodeStar::GitHubRepository',
'AWS::Cognito::IdentityPool',
'AWS::Cognito::IdentityPoolRoleAttachment',
'AWS::Cognito::UserPool',
'AWS::Cognito::UserPoolClient',
'AWS::Cognito::UserPoolGroup',
'AWS::Cognito::UserPoolUser',
'AWS::Cognito::UserPoolUserToGroupAttachment',
'AWS::Config::AggregationAuthorization',
'AWS::Config::ConfigRule',
'AWS::Config::ConfigurationAggregator',
'AWS::Config::ConfigurationRecorder',
'AWS::Config::DeliveryChannel',
'AWS::Config::RemediationConfiguration',
'AWS::DataPipeline::Pipeline',
'AWS::DAX::Cluster',
'AWS::DAX::ParameterGroup',
'AWS::DAX::SubnetGroup',
'AWS::DirectoryService::MicrosoftAD',
'AWS::DirectoryService::SimpleAD',
'AWS::DLM::LifecyclePolicy',
'AWS::DMS::Certificate',
'AWS::DMS::Endpoint',
'AWS::DMS::EventSubscription',
'AWS::DMS::ReplicationInstance',
'AWS::DMS::ReplicationSubnetGroup',
'AWS::DMS::ReplicationTask',
'AWS::DocDB::DBCluster',
'AWS::DocDB::DBClusterParameterGroup',
'AWS::DocDB::DBInstance',
'AWS::DocDB::DBSubnetGroup',
'AWS::DynamoDB::Table',
'AWS::EC2::CapacityReservation',
'AWS::EC2::ClientVpnAuthorizationRule',
'AWS::EC2::ClientVpnEndpoint',
'AWS::EC2::ClientVpnRoute',
'AWS::EC2::ClientVpnTargetNetworkAssociation',
'AWS::EC2::CustomerGateway',
'AWS::EC2::DHCPOptions',
'AWS::EC2::EC2Fleet',
'AWS::EC2::EgressOnlyInternetGateway',
'AWS::EC2::EIP',
'AWS::EC2::EIPAssociation',
'AWS::EC2::FlowLog',
'AWS::EC2::Host',
'AWS::EC2::Instance',
'AWS::EC2::InternetGateway',
'AWS::EC2::LaunchTemplate',
'AWS::EC2::NatGateway',
'AWS::EC2::NetworkAcl',
'AWS::EC2::NetworkAclEntry',
'AWS::EC2::NetworkInterface',
'AWS::EC2::NetworkInterfaceAttachment',
'AWS::EC2::NetworkInterfacePermission',
'AWS::EC2::PlacementGroup',
'AWS::EC2::Route',
'AWS::EC2::RouteTable',
'AWS::EC2::SecurityGroup',
'AWS::EC2::SecurityGroupEgress',
'AWS::EC2::SecurityGroupIngress',
'AWS::EC2::SpotFleet',
'AWS::EC2::Subnet',
'AWS::EC2::SubnetCidrBlock',
'AWS::EC2::SubnetNetworkAclAssociation',
'AWS::EC2::SubnetRouteTableAssociation',
'AWS::EC2::TransitGateway',
'AWS::EC2::TransitGatewayAttachment',
'AWS::EC2::TransitGatewayRoute',
'AWS::EC2::TransitGatewayRouteTable',
'AWS::EC2::TransitGatewayRouteTableAssociation',
'AWS::EC2::TransitGatewayRouteTablePropagation',
'AWS::EC2::Volume',
'AWS::EC2::VolumeAttachment',
'AWS::EC2::VPC',
'AWS::EC2::VPCCidrBlock',
'AWS::EC2::VPCDHCPOptionsAssociation',
'AWS::EC2::VPCEndpoint',
'AWS::EC2::VPCEndpointConnectionNotification',
'AWS::EC2::VPCEndpointService',
'AWS::EC2::VPCEndpointServicePermissions',
'AWS::EC2::VPCGatewayAttachment',
'AWS::EC2::VPCPeeringConnection',
'AWS::EC2::VPNConnection',
'AWS::EC2::VPNConnectionRoute',
'AWS::EC2::VPNGateway',
'AWS::EC2::VPNGatewayRoutePropagation',
'AWS::ECR::Repository',
'AWS::ECS::Cluster',
'AWS::ECS::Service',
'AWS::ECS::TaskDefinition',
'AWS::EFS::FileSystem',
'AWS::EFS::MountTarget',
'AWS::EKS::Cluster',
'AWS::ElastiCache::CacheCluster',
'AWS::ElastiCache::ParameterGroup',
'AWS::ElastiCache::ReplicationGroup',
'AWS::ElastiCache::SecurityGroup',
'AWS::ElastiCache::SecurityGroupIngress',
'AWS::ElastiCache::SubnetGroup',
'AWS::Elasticsearch::Domain',
'AWS::ElasticBeanstalk::Application',
'AWS::ElasticBeanstalk::ApplicationVersion',
'AWS::ElasticBeanstalk::ConfigurationTemplate',
'AWS::ElasticBeanstalk::Environment',
'AWS::ElasticLoadBalancing::LoadBalancer',
'AWS::ElasticLoadBalancingV2::Listener',
'AWS::ElasticLoadBalancingV2::ListenerCertificate',
'AWS::ElasticLoadBalancingV2::ListenerRule',
'AWS::ElasticLoadBalancingV2::LoadBalancer',
'AWS::ElasticLoadBalancingV2::TargetGroup',
'AWS::EMR::Cluster',
'AWS::EMR::InstanceFleetConfig',
'AWS::EMR::InstanceGroupConfig',
'AWS::EMR::SecurityConfiguration',
'AWS::EMR::Step',
'AWS::FSx::FileSystem',
'AWS::GameLift::Alias',
'AWS::GameLift::Build',
'AWS::GameLift::Fleet',
'AWS::Glue::Classifier',
'AWS::Glue::Connection',
'AWS::Glue::Crawler',
'AWS::Glue::Database',
'AWS::Glue::DataCatalogEncryptionSettings',
'AWS::Glue::DevEndpoint',
'AWS::Glue::Job',
'AWS::Glue::Partition',
'AWS::Glue::SecurityConfiguration',
'AWS::Glue::Table',
'AWS::Glue::Trigger',
'AWS::GuardDuty::Detector',
'AWS::GuardDuty::Filter',
'AWS::GuardDuty::IPSet',
'AWS::GuardDuty::Master',
'AWS::GuardDuty::Member',
'AWS::GuardDuty::ThreatIntelSet',
'AWS::IAM::AccessKey',
'AWS::IAM::Group',
'AWS::IAM::InstanceProfile',
'AWS::IAM::ManagedPolicy',
'AWS::IAM::Policy',
'AWS::IAM::Role',
'AWS::IAM::ServiceLinkedRole',
'AWS::IAM::User',
'AWS::IAM::UserToGroupAddition',
'AWS::Inspector::AssessmentTarget',
'AWS::Inspector::AssessmentTemplate',
'AWS::Inspector::ResourceGroup',
'AWS::IoT::Certificate',
'AWS::IoT::Policy',
'AWS::IoT::PolicyPrincipalAttachment',
'AWS::IoT::Thing',
'AWS::IoT::ThingPrincipalAttachment',
'AWS::IoT::TopicRule',
'AWS::IoT1Click::Device',
'AWS::IoT1Click::Placement',
'AWS::IoT1Click::Project',
'AWS::IoTAnalytics::Channel',
'AWS::IoTAnalytics::Dataset',
'AWS::IoTAnalytics::Datastore',
'AWS::IoTAnalytics::Pipeline',
'AWS::IoTEvents::DetectorModel',
'AWS::IoTEvents::Input',
'AWS::Greengrass::ConnectorDefinition',
'AWS::Greengrass::ConnectorDefinitionVersion',
'AWS::Greengrass::CoreDefinition',
'AWS::Greengrass::CoreDefinitionVersion',
'AWS::Greengrass::DeviceDefinition',
'AWS::Greengrass::DeviceDefinitionVersion',
'AWS::Greengrass::FunctionDefinition',
'AWS::Greengrass::FunctionDefinitionVersion',
'AWS::Greengrass::Group',
'AWS::Greengrass::GroupVersion',
'AWS::Greengrass::LoggerDefinition',
'AWS::Greengrass::LoggerDefinitionVersion',
'AWS::Greengrass::ResourceDefinition',
'AWS::Greengrass::ResourceDefinitionVersion',
'AWS::Greengrass::SubscriptionDefinition',
'AWS::Greengrass::SubscriptionDefinitionVersion',
'AWS::IoTThingsGraph::FlowTemplate',
'AWS::Kinesis::Stream',
'AWS::Kinesis::StreamConsumer',
'AWS::KinesisAnalytics::Application',
'AWS::KinesisAnalytics::ApplicationOutput',
'AWS::KinesisAnalytics::ApplicationReferenceDataSource',
'AWS::KinesisAnalyticsV2::Application',
'AWS::KinesisAnalyticsV2::ApplicationCloudWatchLoggingOption',
'AWS::KinesisAnalyticsV2::ApplicationOutput',
'AWS::KinesisAnalyticsV2::ApplicationReferenceDataSource',
'AWS::KinesisFirehose::DeliveryStream',
'AWS::KMS::Alias',
'AWS::KMS::Key',
'AWS::Lambda::Alias',
'AWS::Lambda::EventSourceMapping',
'AWS::Lambda::Function',
'AWS::Lambda::LayerVersion',
'AWS::Lambda::LayerVersionPermission',
'AWS::Lambda::Permission',
'AWS::Lambda::Version',
'AWS::MediaLive::Channel',
'AWS::MediaLive::Input',
'AWS::MediaLive::InputSecurityGroup',
'AWS::MediaStore::Container',
'AWS::MSK::Cluster',
'AWS::Neptune::DBCluster',
'AWS::Neptune::DBClusterParameterGroup',
'AWS::Neptune::DBInstance',
'AWS::Neptune::DBParameterGroup',
'AWS::Neptune::DBSubnetGroup',
'AWS::OpsWorks::App',
'AWS::OpsWorks::ElasticLoadBalancerAttachment',
'AWS::OpsWorks::Instance',
'AWS::OpsWorks::Layer',
'AWS::OpsWorks::Stack',
'AWS::OpsWorks::UserProfile',
'AWS::OpsWorks::Volume',
'AWS::OpsWorksCM::Server',
'AWS::Pinpoint::ADMChannel',
'AWS::Pinpoint::APNSChannel',
'AWS::Pinpoint::APNSSandboxChannel',
'AWS::Pinpoint::APNSVoipChannel',
'AWS::Pinpoint::APNSVoipSandboxChannel',
'AWS::Pinpoint::App',
'AWS::Pinpoint::ApplicationSettings',
'AWS::Pinpoint::BaiduChannel',
'AWS::Pinpoint::Campaign',
'AWS::Pinpoint::EmailChannel',
'AWS::Pinpoint::EventStream',
'AWS::Pinpoint::GCMChannel',
'AWS::Pinpoint::Segment',
'AWS::Pinpoint::SMSChannel',
'AWS::Pinpoint::VoiceChannel',
'AWS::PinpointEmail::ConfigurationSet',
'AWS::PinpointEmail::ConfigurationSetEventDestination',
'AWS::PinpointEmail::DedicatedIpPool',
'AWS::PinpointEmail::Identity',
'AWS::RAM::ResourceShare',
'AWS::RDS::DBCluster',
'AWS::RDS::DBClusterParameterGroup',
'AWS::RDS::DBInstance',
'AWS::RDS::DBParameterGroup',
'AWS::RDS::DBSecurityGroup',
'AWS::RDS::DBSecurityGroupIngress',
'AWS::RDS::DBSubnetGroup',
'AWS::RDS::EventSubscription',
'AWS::RDS::OptionGroup',
'AWS::Redshift::Cluster',
'AWS::Redshift::ClusterParameterGroup',
'AWS::Redshift::ClusterSecurityGroup',
'AWS::Redshift::ClusterSecurityGroupIngress',
'AWS::Redshift::ClusterSubnetGroup',
'AWS::RoboMaker::Fleet',
'AWS::RoboMaker::Robot',
'AWS::RoboMaker::RobotApplication',
'AWS::RoboMaker::RobotApplicationVersion',
'AWS::RoboMaker::SimulationApplication',
'AWS::RoboMaker::SimulationApplicationVersion',
'AWS::Route53::HealthCheck',
'AWS::Route53::HostedZone',
'AWS::Route53::RecordSet',
'AWS::Route53::RecordSetGroup',
'AWS::Route53Resolver::ResolverEndpoint',
'AWS::Route53Resolver::ResolverRule',
'AWS::Route53Resolver::ResolverRuleAssociation',
'AWS::S3::Bucket',
'AWS::S3::BucketPolicy',
'AWS::SageMaker::CodeRepository',
'AWS::SageMaker::Endpoint',
'AWS::SageMaker::EndpointConfig',
'AWS::SageMaker::Model',
'AWS::SageMaker::NotebookInstance',
'AWS::SageMaker::NotebookInstanceLifecycleConfig',
'AWS::SecretsManager::ResourcePolicy',
'AWS::SecretsManager::RotationSchedule',
'AWS::SecretsManager::Secret',
'AWS::SecretsManager::SecretTargetAttachment',
'AWS::ServiceCatalog::AcceptedPortfolioShare',
'AWS::ServiceCatalog::CloudFormationProduct',
'AWS::ServiceCatalog::CloudFormationProvisionedProduct',
'AWS::ServiceCatalog::LaunchNotificationConstraint',
'AWS::ServiceCatalog::LaunchRoleConstraint',
'AWS::ServiceCatalog::LaunchTemplateConstraint',
'AWS::ServiceCatalog::Portfolio',
'AWS::ServiceCatalog::PortfolioPrincipalAssociation',
'AWS::ServiceCatalog::PortfolioProductAssociation',
'AWS::ServiceCatalog::PortfolioShare',
'AWS::ServiceCatalog::ResourceUpdateConstraint',
'AWS::ServiceCatalog::StackSetConstraint',
'AWS::ServiceCatalog::TagOption',
'AWS::ServiceCatalog::TagOptionAssociation',
'AWS::SecurityHub::Hub',
'AWS::SES::ConfigurationSet',
'AWS::SES::ConfigurationSetEventDestination',
'AWS::SES::ReceiptFilter',
'AWS::SES::ReceiptRule',
'AWS::SES::ReceiptRuleSet',
'AWS::SES::Template',
'AWS::SDB::Domain',
'AWS::SNS::Subscription',
'AWS::SNS::Topic',
'AWS::SNS::TopicPolicy',
'AWS::SQS::Queue',
'AWS::SQS::QueuePolicy',
'AWS::StepFunctions::Activity',
'AWS::StepFunctions::StateMachine',
'AWS::SSM::Association',
'AWS::SSM::Document',
'AWS::SSM::MaintenanceWindow',
'AWS::SSM::MaintenanceWindowTarget',
'AWS::SSM::MaintenanceWindowTask',
'AWS::SSM::Parameter',
'AWS::SSM::PatchBaseline',
'AWS::SSM::ResourceDataSync',
'AWS::Transfer::Server',
'AWS::Transfer::User',
'AWS::WAF::ByteMatchSet',
'AWS::WAF::IPSet',
'AWS::WAF::Rule',
'AWS::WAF::SizeConstraintSet',
'AWS::WAF::SqlInjectionMatchSet',
'AWS::WAF::WebACL',
'AWS::WAF::XssMatchSet',
'AWS::WAFRegional::ByteMatchSet',
'AWS::WAFRegional::GeoMatchSet',
'AWS::WAFRegional::IPSet',
'AWS::WAFRegional::RateBasedRule',
'AWS::WAFRegional::RegexPatternSet',
'AWS::WAFRegional::Rule',
'AWS::WAFRegional::SizeConstraintSet',
'AWS::WAFRegional::SqlInjectionMatchSet',
'AWS::WAFRegional::WebACL',
'AWS::WAFRegional::WebACLAssociation',
'AWS::WAFRegional::XssMatchSet',
'AWS::WorkSpaces::Workspace'
]
// npx ts-node _scratch.ts
import fetch from 'node-fetch'
import { AWS_LISTED_TYPES } from './AWS_ListedTypesInTheDocs'
// import path from 'path'
// import fs from 'fs'
const zip = <T, U>(A: T[], B: U[]) => {
let ret: [T, U][]
if (A.length !== B.length) {
throw new Error('not same length')
}
if (A.length < B.length) {
ret = A.map((v, i) => {
return [A[i], B[i]]
})
} else {
ret = B.map((v, i) => {
return [A[i], B[i]]
})
}
return ret
}
const setDiff = (A: Set<string>, B: Set<string>): string[] => {
return Array.from(A.keys()).reduce(
(p, v) => {
return B.has(v) ? [...p] : [v, ...p]
},
[] as string[]
)
}
const setInterSection = (A: Set<string>, B: Set<string>): string[] => {
return Array.from(A.keys()).reduce(
(p, v) => {
return B.has(v) ? [...p, v] : [...p]
},
[] as string[]
)
}
;(async () => {
// setup the batch of network calls.
/*
on url: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html
run this in console to update the URLs:
```js
const listofCDNEndpoints = Array.from(document.querySelectorAll('#w222ab1c21c14c13 > tbody > tr > td:nth-child(3) > p > a'))
listofCDNEndpoints.forEach(e=> console.log(e.href, '//' ,e.parentElement.parentElement.parentElement.childNodes[3].innerText))
```
*/
const cloudfrontCDNs = [
'd2senuesg1djtx', // ap-south-1
'd2zq80gdmjim8k', // ap-northeast-3
'd1ane3fvebulky', // ap-northeast-2
'doigdx0kgq9el', // ap-southeast-1
'd2stg8d246z9di', // ap-southeast-2
'd33vqc0rt9ld30', // ap-northeast-1
'd2s8ygphhesbe7', // ca-central-1
'd1mta8qj7i28i2', // eu-central-1
'd3teyb21fexa9r', // eu-west-1
'd1742qcu2c1ncx', // eu-west-2
'd2d0mfegowb3wk', // eu-west-3
'diy8iv58sj6ba', // eu-north-1
'd3c9jyj3w509b0', // sa-east-1
'd1uauaxba7bl26', // us-east-1
'dnwj8swjjbsbt', // us-east-2
'd68hl49wbnanq', // us-west-1
'd201a2mn26r7lk' // us-west-2
]
const _path = 'latest/gzip/CloudFormationResourceSpecification.json'
const results = await Promise.all(
cloudfrontCDNs.map(subdomain => fetch(`https://${subdomain}.cloudfront.net/${_path}`))
)
// with responses availble, drop them on to the fs via createWriteStream
const zipped = zip(cloudfrontCDNs, results)
// Section Deals with making a cache on the fs
//
/*
const fileDrops = zipped.map(async ([sub, r]) => {
const res = await r.json()
const _writePath = path.resolve(process.cwd(), `${sub}.json`)
const f = fs.createWriteStream(_writePath)
f.write(Buffer.from(JSON.stringify(res, null, 4)))
f.close()
})
await Promise.all(fileDrops)
const jq_filter =
'[ .PropertyTypes | to_entries[] ] | map( select( .value | has( "Properties" )!=true ))'
// look throutgh responses on fs
fs.readdir('.', async (err, files) => {
const importedResponses = await Promise.all(
files.filter(f => f.endsWith('.json')).map(f => import(path.resolve(process.cwd(), `${f}`)))
)
console.log({ importedResponses })
})
*/
const d1 = await Promise.all(zipped.map(async ([sub, Resp]) => [sub, await Resp.json()]))
const d2 = d1.reduce((prior, [sub, data]) => ({ ...prior, [`${sub}`]: data }), {}) as {
[s: string]: {
PropertyTypes: object
ResourceTypes: object
ResourceSpecificationVersion: '5.0.0'
}
}
// console.log({ d2 })
/**
* ADD YOUR VALIDATION RULES, ADD THEM HERE
* REALLY WhAT EVER YOU CAN THINK OF
*/
// Setup Validation Rules
const PropertyRules = [
(name: string, data: any, propMap: any, resMap: any) => {
// Every Property Entry should have a `Properties` entry
return 'Properties' in data ? true : `${name} : Missing Properties`
},
(name: string, data: any, propMap: any, resMap: any) => {
// Every Property Entry should have a `Documentation` entry
return 'Documentation' in data ? true : `${name} : Missing Documentation`
}
] as validationFn[]
const ResourceRules = [
(name: string, data: any, propMap: any, resMap: any) => {
return 'Properties' in data ? true : `${name} : Missing Properties`
},
(name: string, data: any, propMap: any, resMap: any) => {
return 'Documentation' in data ? true : `${name} : Missing Documentation`
},
(name: string, data: any, propMap: any, resMap: any) => {
return AWS_LISTED_TYPES.includes(name) ? true : `Listed but not Covered w/ Sepcfile : ${name}`
}
] as validationFn[]
// perhaps grow this into more a structure output as oppose to a string output
interface validationFn {
(name: string, data: any, propMap: any, resMap: any): boolean | string
}
// Drive through the data
Object.entries(d2).map(([sub, urlRespData]) => {
console.log(
{ v: urlRespData.ResourceSpecificationVersion },
`https://${sub}.cloudfront.net/${_path}`
)
const rValidations = Object.entries(urlRespData.ResourceTypes).map(([name, rData]) => {
const errList = ResourceRules.reduce(
(p, f) => {
const r = f(name, rData, urlRespData.ResourceTypes, urlRespData.PropertyTypes)
return typeof r === 'string' ? [...p, r] : [...p]
},
[] as string[]
)
return errList.length > 0 ? errList : true
})
const pValidations = Object.entries(urlRespData.PropertyTypes).map(([name, pData]) => {
const errList = PropertyRules.reduce(
(p, f) => {
const r = f(name, pData, urlRespData.ResourceTypes, urlRespData.PropertyTypes)
return typeof r === 'string' ? [...p, r] : [...p]
},
[] as string[]
)
return errList.length > 0 ? errList : true
})
const listedNotCovered = ((subdomain, data) => {
const listed = new Set(AWS_LISTED_TYPES)
const covered = new Set(Object.keys(data.ResourceTypes))
return setDiff(listed, covered)
})(sub, urlRespData)
console.log({ pValidations: pValidations.filter(e => typeof e !== 'boolean') })
console.log({ rValidations: rValidations.filter(e => typeof e !== 'boolean') })
console.log({ listedNotCovered })
console.log('\n\n')
// console.log({ resourceErrors: rValidations.filter(v => typeof v === 'string') })
// console.log({ propertyErrors: pValidations.filter(v => typeof v === 'string') })
})
})()
@ericdmoore
Copy link
Author

ericdmoore commented Aug 8, 2019

TLDR: AWS Data about Cloudformation types is dirty - and requiring data janitor work. Chose us-west-2 to minimize your work.

Conclusion

Should you care to process the Cloudformation Specfile published in the documentation of AWS Cloudformation - know a few things:

  1. It varies heavily based on which region - I have not been able to to determine if the missing data correlates to services not available in all regions (I'm skeptical this is true - I am betting its just sloppy oversight)
  2. There are logical inconsistencies in everyfile. Aka: You thought Oh its published by AWS - must be the gold standard... wrong.
    All software has bugs; All Data is dirty; and All Absolute Statements should be examine carefully.
  3. Assuming no meaningful omissions of AWS CFM Types from the specfile, then choose us-west-2. It is the most complete and is an average amount of inconsistent. with at least 6 inconsistencies (tested) and 4 types omitted.

I want to start launching out from here regarding AWS outages and operational excellence varying across regions, and while very tempting I am fully aware that I have circumstantial evidence at best, and will refrain from flying too close to the sun for now. Let's just say it does not surprise me that us-west-2 is as close to golden child as it gets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment