Skip to content

Commit

Permalink
feat(refactor): refactor ad hoc base component
Browse files Browse the repository at this point in the history
  • Loading branch information
briancaffey committed Dec 31, 2022
1 parent 5a2ff1e commit 4621575
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 144 deletions.
2 changes: 1 addition & 1 deletion examples/ad-hoc/base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const adHocBaseEnv = new AdHocBaseEnvComponent('myAdHocEnv', {
});

export const vpcId = adHocBaseEnv.vpc.vpcId;
export const assetsBucket = adHocBaseEnv.assetsBucket.id;
export const assetsBucketName = adHocBaseEnv.assetsBucket.id;
export const privateSubnetIds = adHocBaseEnv.vpc.privateSubnetIds;
export const appSgId = adHocBaseEnv.appSecurityGroup.id;
export const albSgId = adHocBaseEnv.albSecurityGroup.id;
Expand Down
2 changes: 1 addition & 1 deletion src/components/ad-hoc/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export class AdHocAppComponent extends pulumi.ComponentResource {
taskRoleArn: iamResources.ecsTaskRole.arn,
}, {
// this ensures that the priority of the listener rule for the api service is higher than the frontend service
dependsOn: [apiService.listenerRule]
dependsOn: [apiService]
});

// Celery Default Worker
Expand Down
162 changes: 35 additions & 127 deletions src/components/ad-hoc/base/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as aws from "@pulumi/aws"
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";
import { RdsResources } from '../../internal/rds';
import { AlbResources } from "../../internal/alb";
import { BastionHostResources } from '../../internal/bastion';
import { RdsResources } from '../../internal/rds';
import { registerAutoTags } from "../../../util";
import { SecurityGroupResources } from "../../internal/sg";

// automatically tag all resources
registerAutoTags({
Expand Down Expand Up @@ -47,157 +49,63 @@ export class AdHocBaseEnvComponent extends pulumi.ComponentResource {

const stackName = pulumi.getStack();
this.stackName = stackName;

this.domainName = props.domainName;

const vpc = new awsx.ec2.Vpc(stackName, {
cidrBlock: "10.0.0.0/16",
numberOfAvailabilityZones: 2,
enableDnsHostnames: true,
enableDnsSupport: true
});
}, { parent: this });
this.vpc = vpc;

const assetsBucket = new aws.s3.Bucket("assetsBucket", {
bucket: `${props.domainName.replace(".", "-")}-${stackName}-assets-bucket`
});
bucket: `${props.domainName.replace(".", "-")}-${stackName}-assets-bucket`,
forceDestroy: true
}, { parent: this });
this.assetsBucket = assetsBucket;

const albSecurityGroup = new aws.ec2.SecurityGroup('AlbSecurityGroup', {
description: "Allow traffic from ALB",
vpcId: vpc.vpcId,
ingress: [{
description: "Port 80 Traffic",
fromPort: 80,
toPort: 80,
protocol: "tcp",
cidrBlocks: ["0.0.0.0/0"],
}, {
description: "Port 443 Traffic",
fromPort: 443,
toPort: 443,
protocol: "tcp",
cidrBlocks: ["0.0.0.0/0"],
}],
egress: [{
fromPort: 0,
toPort: 0,
protocol: "-1",
cidrBlocks: ["0.0.0.0/0"],
}],
});
this.albSecurityGroup = albSecurityGroup;

const appSecurityGroup = new aws.ec2.SecurityGroup('AppSecurityGroup', {
description: "Allow traffic from ALB SG to apps",
vpcId: vpc.vpcId,
ingress: [{
description: "Port 80 Traffic",
fromPort: 0,
toPort: 0,
protocol: "-1",
securityGroups: [albSecurityGroup.id],
},{
description: "Allow traffic from this SG",
fromPort: 0,
toPort: 0,
protocol: "-1",
self: true,
}],
egress: [{
description: "Allow all outbound traffic",
fromPort: 0,
toPort: 0,
protocol: "-1",
cidrBlocks: ["0.0.0.0/0"],
},{
description: "Allow all outbound to this SG",
fromPort: 0,
toPort: 0,
protocol: "-1",
self: true
}],
});
this.appSecurityGroup = appSecurityGroup;

const loadBalancer = new aws.alb.LoadBalancer("LoadBalancer", {
internal: false,
loadBalancerType: "application",
securityGroups: [albSecurityGroup.id],
subnets: vpc.publicSubnetIds,
});
this.alb = loadBalancer;

new aws.alb.TargetGroup("DefaultTg", {
vpcId: vpc.vpc.id,
port: 80,
targetType: "instance",
protocol: "HTTP",
healthCheck: {
protocol: "HTTP",
interval: 300,
path: "/api/health-check/",
timeout: 120,
healthyThreshold: 2,
unhealthyThreshold: 3,
port: '80'
}
});

new aws.alb.Listener("HttpListener", {
loadBalancerArn: loadBalancer.arn,
port: 80,
protocol: "HTTP",
defaultActions: [{
type: "redirect",
redirect: {
port: "443",
protocol: "HTTPS",
statusCode: "HTTP_301",
},
}]
});
const securityGroupResources = new SecurityGroupResources("SecurityGroupResources", {
vpcId: vpc.vpcId
}, { parent: this });
this.appSecurityGroup = securityGroupResources.appSecurityGroup;
this.albSecurityGroup = securityGroupResources.albSecurityGroup;

const httpsListener = new aws.alb.Listener("HttpsListener", {
loadBalancerArn: loadBalancer.arn,
port: 443,
protocol: "HTTPS",
// ALB resources (Load Balancer, Default Target Group, HTTP and HTTPS Listener)
const loadBalancerResources = new AlbResources("AlbResources", {
albSgId: securityGroupResources.albSecurityGroup.id,
certificateArn: props.certificateArn,
defaultActions: [{
type: "fixed-response",
fixedResponse: {
contentType: "text/plain",
messageBody: "Fixed response content",
statusCode: "200",
},
}],
});
this.listener = httpsListener;

const serviceDiscoveryPrivateDnsNamespace = new aws.servicediscovery.PrivateDnsNamespace(
"PrivateDnsNamespace", {
description: "private dns namespace for ad hoc environment",
vpc: vpc.vpc.id,
name: `${stackName}-sd-ns`
}
);
this.serviceDiscoveryNamespace = serviceDiscoveryPrivateDnsNamespace;
publicSubnetIds: vpc.publicSubnetIds,
vpcId: vpc.vpcId,
}, { parent: this });
this.alb = loadBalancerResources.alb;
this.listener = loadBalancerResources.listener;

// CloudMap service discovery is only needed in ad hoc environments
// It is needed to support running redis in our ECS cluster
const sdNameSpace = new aws.servicediscovery.PrivateDnsNamespace("PrivateDnsNamespace", {
description: "private dns namespace for ad hoc environment",
vpc: vpc.vpcId,
name: `${stackName}-sd-ns`
}, { parent: this });
this.serviceDiscoveryNamespace = sdNameSpace;

// RDS
const rdsResources = new RdsResources("RdsResources", {
appSecurityGroup: appSecurityGroup,
appSgId: securityGroupResources.appSecurityGroup.id,
dbSecretName: "DB_SECRET_NAME",
port: 5432,
vpc: vpc
});
vpcId: vpc.vpcId,
privateSubnetIds: vpc.privateSubnetIds
}, { parent: this });
this.databaseInstance = rdsResources.databaseInstance;

// BastionHost
const bastionHost = new BastionHostResources("BastionHostResources", {
appSgId: appSecurityGroup.id,
appSgId: securityGroupResources.appSecurityGroup.id,
rdsAddress: rdsResources.databaseInstance.address,
privateSubnet: vpc.privateSubnetIds[0]
});
}, { parent: this });
this.bastionHostInstanceId = bastionHost.instanceId;
}
}
79 changes: 79 additions & 0 deletions src/components/internal/alb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import * as aws from "@pulumi/aws"
import * as pulumi from "@pulumi/pulumi";

interface AlbResourcesProps {
vpcId: pulumi.Output<string>;
publicSubnetIds: pulumi.Output<string[]>;
albSgId: pulumi.Output<string>;
certificateArn: string;
}

export class AlbResources extends pulumi.ComponentResource {
public readonly listener: aws.alb.Listener;
public readonly alb: aws.alb.LoadBalancer;

/**
* Creates a new static website hosted on AWS.
* @param name The _unique_ name of the resource.
* @param props Props to pass to AdHocBaseEnv component
* @param opts A bag of options that control this resource's behavior.
*/
constructor(name: string, props: AlbResourcesProps, opts?: pulumi.ResourceOptions) {
super(`pulumi-contrib:components:AlbResources`, name, props, opts);

const loadBalancer = new aws.alb.LoadBalancer("LoadBalancer", {
internal: false,
loadBalancerType: "application",
securityGroups: [props.albSgId],
subnets: props.publicSubnetIds,
}, { parent: this });
this.alb = loadBalancer;

new aws.alb.TargetGroup("DefaultTg", {
vpcId: props.vpcId,
port: 80,
targetType: "instance",
protocol: "HTTP",
healthCheck: {
protocol: "HTTP",
interval: 300,
path: "/api/health-check/",
timeout: 120,
healthyThreshold: 2,
unhealthyThreshold: 3,
port: '80'
}
}, { parent: this });

new aws.alb.Listener("HttpListener", {
loadBalancerArn: loadBalancer.arn,
port: 80,
protocol: "HTTP",
defaultActions: [{
type: "redirect",
redirect: {
port: "443",
protocol: "HTTPS",
statusCode: "HTTP_301",
},
}]
}, { parent: this });

const httpsListener = new aws.alb.Listener("HttpsListener", {
loadBalancerArn: loadBalancer.arn,
port: 443,
protocol: "HTTPS",
certificateArn: props.certificateArn,
defaultActions: [{
type: "fixed-response",
fixedResponse: {
contentType: "text/plain",
messageBody: "Fixed response content",
statusCode: "200",
},
}],
}, { parent: this });
this.listener = httpsListener;
}
}

8 changes: 4 additions & 4 deletions src/components/internal/bastion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class BastionHostResources extends pulumi.ComponentResource {
},
}],
}),
});
}, { parent: this });

// policy for BastionHostRole
const policy = new aws.iam.RolePolicy("BastionHostPolicy", {
Expand All @@ -70,13 +70,13 @@ export class BastionHostResources extends pulumi.ComponentResource {
Resource: "*",
}],
}),
});
}, { parent: this });

// instance profile
const instanceProfile = new aws.iam.InstanceProfile("BastionHostInstanceProfile", {
role: bastionHostRole.name,
name: `${stackName}BastionInstanceProfile`
});
}, { parent: this });

// bastion host user data string
const bastionHostUserData = `
Expand Down Expand Up @@ -123,7 +123,7 @@ runcmd:
vpcSecurityGroupIds: [props.appSgId],
subnetId: props.privateSubnet,
userData: bastionHostUserData,
});
}, { parent: this });
this.instanceId = instance.id;
}
}
5 changes: 3 additions & 2 deletions src/components/internal/ecs/web/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class WebEcsService extends pulumi.ComponentResource {
tags: {
Name: `${stackName}-${props.name}-tg`
}
});
}, { parent: this });

// aws ecs service
const ecsService = new aws.ecs.Service(`${props.name}WebService`, {
Expand Down Expand Up @@ -141,6 +141,7 @@ export class WebEcsService extends pulumi.ComponentResource {
subnets: props.privateSubnets
}
}, {
parent: this,
ignoreChanges: ['taskDefinition', 'desiredCount'],
dependsOn: [targetGroup]
});
Expand All @@ -163,7 +164,7 @@ export class WebEcsService extends pulumi.ComponentResource {
}
}
]
});
}, { parent: this});
this.listenerRule = listenerRule;
}
}
Loading

0 comments on commit 4621575

Please sign in to comment.