in packages/aws-cdk-lib/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts [461:582]
constructor(scope: Construct, id: string, props: ApplicationLoadBalancedServiceBaseProps = {}) {
super(scope, id);
if (props.cluster && props.vpc) {
throw new Error('You can only specify either vpc or cluster. Alternatively, you can leave both blank');
}
this.cluster = props.cluster || this.getDefaultCluster(this, props.vpc);
if (props.desiredCount !== undefined && !cdk.Token.isUnresolved(props.desiredCount) && props.desiredCount < 1) {
throw new Error('You must specify a desiredCount greater than 0');
}
this.desiredCount = props.desiredCount || 1;
this.internalDesiredCount = props.desiredCount;
const internetFacing = props.publicLoadBalancer ?? true;
if (props.idleTimeout) {
const idleTimeout = props.idleTimeout.toSeconds();
if (idleTimeout > Duration.seconds(4000).toSeconds() || idleTimeout < Duration.seconds(1).toSeconds()) {
throw new Error('Load balancer idle timeout must be between 1 and 4000 seconds.');
}
}
const lbProps: ApplicationLoadBalancerProps = {
vpc: this.cluster.vpc,
loadBalancerName: props.loadBalancerName,
internetFacing,
idleTimeout: props.idleTimeout,
ipAddressType: props.ipAddressType,
};
const loadBalancer = props.loadBalancer ?? new ApplicationLoadBalancer(this, 'LB', lbProps);
if (props.certificate !== undefined && props.protocol !== undefined && props.protocol !== ApplicationProtocol.HTTPS) {
throw new Error('The HTTPS protocol must be used when a certificate is given');
}
const protocol = props.protocol ?? (props.certificate ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP);
if (protocol !== ApplicationProtocol.HTTPS && props.redirectHTTP === true) {
throw new Error('The HTTPS protocol must be used when redirecting HTTP traffic');
}
const targetProps: AddApplicationTargetsProps = {
protocol: props.targetProtocol ?? ApplicationProtocol.HTTP,
protocolVersion: props.protocolVersion,
};
this.listener = loadBalancer.addListener('PublicListener', {
protocol,
port: props.listenerPort,
open: props.openListener ?? true,
sslPolicy: props.sslPolicy,
});
this.targetGroup = this.listener.addTargets('ECS', targetProps);
if (protocol === ApplicationProtocol.HTTPS) {
if (props.certificate !== undefined) {
this.certificate = props.certificate;
} else {
if (typeof props.domainName === 'undefined' || typeof props.domainZone === 'undefined') {
throw new Error('A domain name and zone is required when using the HTTPS protocol');
}
this.certificate = new Certificate(this, 'Certificate', {
domainName: props.domainName,
validation: CertificateValidation.fromDns(props.domainZone),
});
}
}
if (this.certificate !== undefined) {
this.listener.addCertificates('Arns', [ListenerCertificate.fromCertificateManager(this.certificate)]);
}
if (props.redirectHTTP) {
this.redirectListener = loadBalancer.addListener('PublicRedirectListener', {
protocol: ApplicationProtocol.HTTP,
port: 80,
open: props.openListener ?? true,
defaultAction: ListenerAction.redirect({
port: props.listenerPort?.toString() || '443',
protocol: ApplicationProtocol.HTTPS,
permanent: true,
}),
});
}
let domainName = loadBalancer.loadBalancerDnsName;
if (typeof props.domainName !== 'undefined') {
if (typeof props.domainZone === 'undefined') {
throw new Error('A Route53 hosted domain zone name is required to configure the specified domain name');
}
switch (props.recordType ?? ApplicationLoadBalancedServiceRecordType.ALIAS) {
case ApplicationLoadBalancedServiceRecordType.ALIAS:
let aliasRecord = new ARecord(this, 'DNS', {
zone: props.domainZone,
recordName: props.domainName,
target: RecordTarget.fromAlias(new LoadBalancerTarget(loadBalancer)),
});
domainName = aliasRecord.domainName;
break;
case ApplicationLoadBalancedServiceRecordType.CNAME:
let cnameRecord = new CnameRecord(this, 'DNS', {
zone: props.domainZone,
recordName: props.domainName,
domainName: loadBalancer.loadBalancerDnsName,
});
domainName = cnameRecord.domainName;
break;
case ApplicationLoadBalancedServiceRecordType.NONE:
// Do not create a DNS record
break;
}
}
if (loadBalancer instanceof ApplicationLoadBalancer) {
this._applicationLoadBalancer = loadBalancer;
}
new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: loadBalancer.loadBalancerDnsName });
new cdk.CfnOutput(this, 'ServiceURL', { value: protocol.toLowerCase() + '://' + domainName });
}