-
-
Save tolicodes/1f00b63e90162bb1e690eab3acfe29be to your computer and use it in GitHub Desktop.
Pulumi Components
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
import * as aws from '@pulumi/aws'; | |
import * as awsx from '@pulumi/awsx'; | |
import * as pulumi from '@pulumi/pulumi'; | |
export interface IAutoScaleFargateServiceArgs { | |
iamRole: aws.iam.Role; | |
service: awsx.ecs.FargateService; | |
cluster: awsx.ecs.Cluster; | |
serviceName: string; | |
maxCount: number; | |
minCount: number; | |
CPUThreshold: number; | |
memoryThreshold: number; | |
} | |
export default class AutoScaleFargateService extends pulumi.ComponentResource { | |
public readonly /*out*/ autoScaleTarget: pulumi.Output<aws.appautoscaling.Target>; | |
public readonly /*out*/ cpuScalingPolicy: pulumi.Output<aws.appautoscaling.Policy>; | |
public readonly /*out*/ memoryScalingPolicy: pulumi.Output<aws.appautoscaling.Policy>; | |
constructor( | |
name: string, | |
{ | |
iamRole, | |
service, | |
cluster, | |
serviceName, | |
maxCount, | |
minCount, | |
CPUThreshold, | |
memoryThreshold, | |
}: IAutoScaleFargateServiceArgs, | |
opts?: pulumi.ResourceOptions, | |
) { | |
super('AutoScaleFargateService', name, {}, opts); | |
const stack = pulumi.getStack(); | |
this.autoScaleTarget = pulumi.output( | |
new aws.appautoscaling.Target( | |
`appautoscaling-target-${serviceName}-${stack}`, | |
{ | |
// max/min task instances | |
maxCapacity: maxCount, | |
minCapacity: minCount, | |
roleArn: iamRole.arn, | |
resourceId: pulumi.interpolate`service/${cluster.cluster.name}/${service.service.name}`, | |
scalableDimension: 'ecs:service:DesiredCount', | |
serviceNamespace: 'ecs', | |
}, | |
), | |
); | |
const policyOpts = { | |
policyType: 'TargetTrackingScaling', | |
resourceId: this.autoScaleTarget.resourceId, | |
scalableDimension: this.autoScaleTarget.scalableDimension, | |
serviceNamespace: this.autoScaleTarget.serviceNamespace, | |
}; | |
this.cpuScalingPolicy = pulumi.output( | |
new aws.appautoscaling.Policy( | |
`appautoscaling-policy-cpu-${serviceName}-${stack}`, | |
{ | |
...policyOpts, | |
targetTrackingScalingPolicyConfiguration: { | |
predefinedMetricSpecification: { | |
predefinedMetricType: 'ECSServiceAverageCPUUtilization', | |
}, | |
// scale so that we use max x% CPU | |
targetValue: CPUThreshold, | |
}, | |
}, | |
), | |
); | |
this.memoryScalingPolicy = pulumi.output( | |
new aws.appautoscaling.Policy( | |
`appautoscaling-policy-memory-${serviceName}-${stack}`, | |
{ | |
...policyOpts, | |
targetTrackingScalingPolicyConfiguration: { | |
predefinedMetricSpecification: { | |
predefinedMetricType: 'ECSServiceAverageMemoryUtilization', | |
}, | |
// scale so that we use max x% Memory | |
targetValue: memoryThreshold, | |
}, | |
}, | |
), | |
); | |
super.registerOutputs({ | |
cpuScalingPolicy: this.cpuScalingPolicy, | |
memoryScalingPolicy: this.memoryScalingPolicy, | |
autoScaleTarget: this.autoScaleTarget, | |
}); | |
} | |
} |
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
import * as aws from '@pulumi/aws'; | |
import * as awsx from '@pulumi/awsx'; | |
import * as pulumi from '@pulumi/pulumi'; | |
import ValidatedCertificate from './validated-certificate'; | |
const DEFAULT_CLIENT_CIDR_BLOCK = '11.0.0.0/22'; | |
interface IValidatedCertificateOpts { | |
hostedZoneId: pulumi.Input<string>; | |
domainName: pulumi.Input<string>; | |
clientCidrBlock?: pulumi.Input<string>; | |
samlProviderArn: pulumi.Input<string>; | |
vpc: awsx.ec2.Vpc; | |
} | |
export default class ClientVPNEndpoint extends pulumi.ComponentResource { | |
public readonly /*out*/ endpoint: pulumi.Output<aws.ec2clientvpn.Endpoint>; | |
public readonly /*out*/ networkAssociation: pulumi.Output<aws.ec2clientvpn.NetworkAssociation>; | |
public readonly /*out*/ authorizationRule: pulumi.Output<aws.ec2clientvpn.AuthorizationRule>; | |
constructor( | |
name: string, | |
{ | |
hostedZoneId, | |
domainName, | |
clientCidrBlock = DEFAULT_CLIENT_CIDR_BLOCK, | |
samlProviderArn, | |
vpc, | |
}: IValidatedCertificateOpts, | |
opts?: pulumi.ResourceOptions, | |
) { | |
super('ClientVPNEndpoint', name, {}, opts); | |
const validatedCertificate = new ValidatedCertificate( | |
`${name}-validated-certificate`, | |
{ | |
hostedZoneId, | |
domainName, | |
}, | |
); | |
const endpointName = `${name}-client-vpn-endpoint`; | |
this.endpoint = pulumi.output(new aws.ec2clientvpn.Endpoint(endpointName, { | |
tags: { | |
Name: endpointName, | |
}, | |
serverCertificateArn: validatedCertificate.certificateArn, | |
clientCidrBlock, | |
splitTunnel: true, | |
authenticationOptions: [ | |
{ | |
type: 'federated-authentication', | |
samlProviderArn, | |
}, | |
], | |
connectionLogOptions: { | |
enabled: false, | |
}, | |
})); | |
// TODO: what if there are multiple private subnets? will this be a problem? | |
// what is a scenario where we need to access multiple subnets? | |
const defaultPrivateSubnetId = pulumi.output(vpc.privateSubnetIds)[0]; | |
const defaultPrivateSubnetCidrBlock = pulumi | |
.output(vpc.privateSubnets)[0].subnet.cidrBlock; | |
// allows the endpoint to access these subnets | |
this.networkAssociation = pulumi.output(new aws.ec2clientvpn.NetworkAssociation( | |
`${name}-network-association`, | |
{ | |
clientVpnEndpointId: this.endpoint.id, | |
subnetId: defaultPrivateSubnetId, | |
}, | |
)); | |
// allows the following subnet groups to access these subnets | |
this.authorizationRule = pulumi.output(new aws.ec2clientvpn.AuthorizationRule( | |
`${name}-authorization-rule`, | |
{ | |
clientVpnEndpointId: this.endpoint.id, | |
targetNetworkCidr: defaultPrivateSubnetCidrBlock, | |
authorizeAllGroups: true, | |
}, | |
)); | |
super.registerOutputs({ | |
endpoint: this.endpoint, | |
networkAssociation: this.networkAssociation, | |
authorizationRule: this.authorizationRule, | |
}); | |
} | |
} |
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
import * as aws from '@pulumi/aws'; | |
import * as pulumi from '@pulumi/pulumi'; | |
interface IValidatedCertificateOpts { | |
hostedZoneId: pulumi.Input<string>; | |
domainName: pulumi.Input<string>; | |
} | |
export default class ValidatedCertificate extends pulumi.ComponentResource { | |
public readonly /*out*/ certificateArn: pulumi.Output<string>; | |
public readonly /*out*/ certificate: pulumi.Output<aws.acm.Certificate>; | |
constructor( | |
name: string, | |
{ hostedZoneId, domainName }: IValidatedCertificateOpts, | |
opts?: pulumi.ResourceOptions, | |
) { | |
super('ValidatedCertificate', name, {}, opts); | |
this.certificate = pulumi.output( | |
new aws.acm.Certificate(`${name}-certificate`, { | |
domainName, | |
validationMethod: 'DNS', | |
}), | |
); | |
const { resourceRecordName, resourceRecordType, resourceRecordValue } = | |
this.certificate.domainValidationOptions[0]; | |
// Create a DNS record to prove that we _own_ the domain we're requesting a certificate for. | |
const certificateValidationDomain = new aws.route53.Record( | |
`${name}-certificate-domain-validation`, | |
{ | |
name: resourceRecordName, | |
zoneId: hostedZoneId, | |
type: resourceRecordType, | |
records: [resourceRecordValue], | |
ttl: 600, | |
}, | |
); | |
/** | |
* This is a _special_ resource that waits for ACM to complete validation via the DNS record | |
* checking for a status of 'ISSUED' on the certificate itself. No actual resources are | |
* created (or updated or deleted). | |
* | |
* See https://www.terraform.io/docs/providers/aws/r/acm_certificate_validation.html for slightly more detail | |
* and https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/resource_aws_acm_certificate_validation.go | |
* for the actual implementation. | |
*/ | |
const certificateValidation = new aws.acm.CertificateValidation( | |
`${name}-certificate-validation`, | |
{ | |
certificateArn: this.certificate.arn, | |
validationRecordFqdns: [certificateValidationDomain.fqdn], | |
}, | |
); | |
this.certificateArn = certificateValidation.certificateArn; | |
super.registerOutputs({ | |
certificate: this.certificate, | |
certificateArn: this.certificateArn, | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment