Skip to content

Commit

Permalink
Merge pull request #35 from bmaidics/iot_multi_dep
Browse files Browse the repository at this point in the history
IOT multi deployment support
  • Loading branch information
jfallows authored Nov 13, 2024
2 parents 7fb616b + 630fd1f commit db68ae8
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 39 deletions.
11 changes: 11 additions & 0 deletions amazon-msk/cdktf/iot-ingest-and-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ Create a `.env` file from the example file.
cp .env.example .env
```

### Internet Gateway ID

If you already have an Internet Gateway in the MSK's VPN it should be provided via the `IGW_ID` environment variable. If not set the deployment will attempt to create on in the VPC.

To query the IGW_ID of your MSK's VPN use the following comman:
```bash
SUBNET_ID=$(aws kafka describe-cluster --cluster-arn <you-msk-arn> --query "ClusterInfo.BrokerNodeGroupInfo.ClientSubnets[0]" --output text)
VPC_ID=$(aws ec2 describe-subnets --subnet-ids $SUBNET_ID --query "Subnets[0].VpcId" --output text)
aws ec2 describe-internet-gateways --filters "Name=attachment.vpc-id,Values=$VPC_ID" --query "InternetGateways[0].InternetGatewayId" --output text
```

### Kafka topics

By default, the deployment creates the provided Kafka topics required by Zilla Plus. To disable this set the environment variable `MQTT_KAFKA_TOPIC_CREATION_DISABLED` to `true` and set the `kafka_topic_mqtt_sessions`, `kafka_topic_mqtt_messages`, and `kafka_topic_mqtt_retained` in your `terraform.tfvars` file.
Expand Down
26 changes: 13 additions & 13 deletions amazon-msk/cdktf/iot-ingest-and-control/__tests__/main-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,28 @@ describe("Zilla Plus IOT and Control Stack Test", () => {
{
desired_capacity: "${var.zilla_plus_capacity}",
launch_template: {
id: "${aws_launch_template.ZillaPlusLaunchTemplate.id}",
id: "${aws_launch_template.ZillaPlusLaunchTemplate-test.id}",
},
max_size: 5,
min_size: 1,
target_group_arns: ["${aws_lb_target_group.NLBTargetGroup.arn}"],
target_group_arns: ["${aws_lb_target_group.NLBTargetGroup-test.arn}"],
vpc_zone_identifier: [
"${aws_subnet.PublicSubnet1.id}",
"${aws_subnet.PublicSubnet2.id}",
"${aws_subnet.PublicSubnet1-test.id}",
"${aws_subnet.PublicSubnet2-test.id}",
],
}
);
});

it("should have cloudwatch group resource", async () => {
expect(output).toHaveResourceWithProperties(CloudwatchLogGroup, {
name: "${var.cloudwatch_logs_group}",
name: "${var.cloudwatch_logs_group-test}",
});
});

it("should have load balancer target group", async () => {
expect(output).toHaveResourceWithProperties(LbTargetGroup, {
name: "nlb-target-group",
name: "nlb-tg-test",
port: "${var.public_tcp_port}",
protocol: "TCP",
vpc_id: "${data.aws_vpc.Vpc.id}",
Expand All @@ -55,11 +55,11 @@ describe("Zilla Plus IOT and Control Stack Test", () => {
enable_cross_zone_load_balancing: true,
internal: false,
load_balancer_type: "network",
name: "network-load-balancer",
security_groups: ["${aws_security_group.ZillaPlusSecurityGroup.id}"],
name: "nlb-test",
security_groups: ["${aws_security_group.ZillaPlusSecurityGroup-test.id}"],
subnets: [
"${aws_subnet.PublicSubnet1.id}",
"${aws_subnet.PublicSubnet2.id}",
"${aws_subnet.PublicSubnet1-test.id}",
"${aws_subnet.PublicSubnet2-test.id}",
],
});
});
Expand All @@ -68,11 +68,11 @@ describe("Zilla Plus IOT and Control Stack Test", () => {
expect(output).toHaveResourceWithProperties(LbListener, {
default_action: [
{
target_group_arn: "${aws_lb_target_group.NLBTargetGroup.arn}",
target_group_arn: "${aws_lb_target_group.NLBTargetGroup-test.arn}",
type: "forward",
},
],
load_balancer_arn: "${aws_lb.NetworkLoadBalancer.arn}",
load_balancer_arn: "${aws_lb.NetworkLoadBalancer-test.arn}",
port: "${var.public_tcp_port}",
protocol: "TCP",
});
Expand All @@ -90,7 +90,7 @@ describe("Zilla Plus IOT and Control Stack Test", () => {
{
associate_public_ip_address: "true",
device_index: 0,
security_groups: ["${aws_security_group.ZillaPlusSecurityGroup.id}"],
security_groups: ["${aws_security_group.ZillaPlusSecurityGroup-test.id}"],
},
],
});
Expand Down
74 changes: 48 additions & 26 deletions amazon-msk/cdktf/iot-ingest-and-control/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { SecurityGroup } from "@cdktf/provider-aws/lib/security-group";
import { UserVariables } from "./variables";
import Mustache = require("mustache");
import fs = require("fs");
import { DataAwsInternetGateway } from "@cdktf/provider-aws/lib/data-aws-internet-gateway";

interface TemplateData {
name: string;
Expand Down Expand Up @@ -87,31 +88,52 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
name: "vpc-id",
values: [vpc.id],
},
{
name: "mapPublicIpOnLaunch",
values: ["true"]
},
],
});

const igw = new InternetGateway(this, "InternetGateway", {
vpcId: vpc.id,
tags: {
Name: "my-igw",
},
});
let igwId;
if (userVariables.igwId)
{
const existingIgw = new DataAwsInternetGateway(this, `ExistingInternetGateway-${id}`, {
filter: [
{
name: "attachment.vpc-id",
values: [vpc.id],
},
],
});
igwId = existingIgw.id;
}
else
{
const igw = new InternetGateway(this, `InternetGateway-${id}`, {
vpcId: vpc.id,
tags: {
Name: `my-igw-${id}`,
},
});
igwId = igw.id;
}

const publicRouteTable = new RouteTable(this, "PublicRouteTable", {
vpcId: vpc.id,
tags: {
Name: "public-route-table",
Name: `public-route-table-${id}`,
},
});

new Route(this, "PublicRoute", {
routeTableId: publicRouteTable.id,
destinationCidrBlock: "0.0.0.0/0",
gatewayId: igw.id,
gatewayId: igwId,
});

const availabilityZones = new DataAwsAvailabilityZones(this, "AZs", {});
const subnetOffset = subnets.ids.length;
const subnetOffset = Fn.lengthOf(subnets.ids);
const subnetMask = Fn.parseint(Fn.element(Fn.split("/", vpc.cidrBlock), 1), 10);
const availableIpv4 = subnet.availableIpAddressCount;
// Math magic to find next power of 2 and based on that the subnetAddressPower
Expand All @@ -121,22 +143,22 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
const subnetIds = [];
for (let i = 1; i < 3; i++) {
const az = Fn.element(availabilityZones.names, i);
const subnetIndex = subnetOffset + i;
const cidrBlock = Fn.cidrsubnet(vpc.cidrBlock, subnetsMax, subnetIndex + i);
const subnetIndex = Op.add(subnetOffset, i);
const cidrBlock = Fn.cidrsubnet(vpc.cidrBlock, subnetsMax, Op.add(subnetIndex, i));

const subnet = new Subnet(this, `PublicSubnet${i}`, {
const subnet = new Subnet(this, `PublicSubnet${i}-${id}`, {
vpcId: vpc.id,
cidrBlock: cidrBlock,
availabilityZone: az,
mapPublicIpOnLaunch: true,
tags: {
Name: `public-subnet--${subnetIndex + 1}`,
Name: `public-subnet-${subnetIndex + 1}-${id}`,
},
});

subnetIds.push(subnet.id);

new RouteTableAssociation(this, `PublicSubnet${i}RouteTableAssociation`, {
new RouteTableAssociation(this, `PublicSubnet${i}RouteTableAssociation-${id}`, {
subnetId: subnet.id,
routeTableId: publicRouteTable.id,
});
Expand Down Expand Up @@ -175,8 +197,8 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {

zillaPlusRole = zillaPlusRoleVar.stringValue;
} else {
const iamRole = new IamRole(this, "zilla_plus_role", {
name: "zilla_plus_role",
const iamRole = new IamRole(this, `zilla_plus_role-${id}`, {
name: `zilla_plus_role-${id}`,
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [
Expand Down Expand Up @@ -228,7 +250,7 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
});

const iamInstanceProfile = new IamInstanceProfile(this, "zilla_plus_instance_profile", {
name: "zilla_plus_role",
name: `zilla_plus_role-${id}`,
role: iamRole.name,
});

Expand Down Expand Up @@ -265,7 +287,7 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
});
zillaPlusSecurityGroups = zillaPlusSecurityGroupsVar.listValue;
} else {
const zillaPlusSG = new SecurityGroup(this, "ZillaPlusSecurityGroup", {
const zillaPlusSG = new SecurityGroup(this, `ZillaPlusSecurityGroup-${id}`, {
vpcId: vpc.id,
description: "Security group for Zilla Plus",
ingress: [
Expand Down Expand Up @@ -334,13 +356,13 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
const defaultLogGroupName = `${id}-group`;
const defaultMetricNamespace = `${id}-namespace`;

const cloudWatchLogsGroup = new TerraformVariable(this, "cloudwatch_logs_group", {
const cloudWatchLogsGroup = new TerraformVariable(this, `cloudwatch_logs_group-${id}`, {
type: "string",
description: "The Cloud Watch log group Zilla Plush should publish logs",
default: defaultLogGroupName,
});

const cloudWatchMetricsNamespace = new TerraformVariable(this, "cloudwatch_metrics_namespace", {
const cloudWatchMetricsNamespace = new TerraformVariable(this, `cloudwatch_metrics_namespace-${id}`, {
type: "string",
description: "The Cloud Watch metrics namespace Zilla Plush should publish metrics",
default: defaultMetricNamespace,
Expand Down Expand Up @@ -375,17 +397,17 @@ export class ZillaPlusIotAndControlStack extends TerraformStack {
owners: ["679593333241"],
});

const nlb = new Lb(this, "NetworkLoadBalancer", {
name: "network-load-balancer",
const nlb = new Lb(this, `NetworkLoadBalancer-${id}`, {
name: `nlb-${id}`,
loadBalancerType: "network",
internal: false,
subnets: subnetIds,
securityGroups: zillaPlusSecurityGroups,
enableCrossZoneLoadBalancing: true,
});

const nlbTargetGroup = new LbTargetGroup(this, "NLBTargetGroup", {
name: "nlb-target-group",
const nlbTargetGroup = new LbTargetGroup(this, `NLBTargetGroup-${id}`, {
name: `nlb-tg-${id}`,
port: publicTcpPort.value,
protocol: "TCP",
vpcId: vpc.id,
Expand Down Expand Up @@ -498,7 +520,7 @@ ${kafkaTopicCreationCommand}
`;

const MSKProxyLaunchTemplate = new launchTemplate.LaunchTemplate(this, "ZillaPlusLaunchTemplate", {
const MSKProxyLaunchTemplate = new launchTemplate.LaunchTemplate(this, `ZillaPlusLaunchTemplate-${id}`, {
imageId: ami.imageId,
instanceType: instanceType.stringValue,
networkInterfaces: [
Expand All @@ -515,7 +537,7 @@ ${kafkaTopicCreationCommand}
userData: Fn.base64encode(userData),
});

new autoscalingGroup.AutoscalingGroup(this, "zillaPlusGroup", {
new autoscalingGroup.AutoscalingGroup(this, `zillaPlusGroup-${id}`, {
vpcZoneIdentifier: subnetIds,
launchTemplate: {
id: MSKProxyLaunchTemplate.id,
Expand Down
2 changes: 2 additions & 0 deletions amazon-msk/cdktf/iot-ingest-and-control/variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class UserVariables extends Construct {
sshKeyEnabled: boolean = false;
cloudwatchDisabled: boolean = false;
mqttKafkaTopicCreationDisabled: boolean = false;
igwId: string | undefined;

constructor(scope: Construct, name: string) {
super(scope, name);
Expand All @@ -18,5 +19,6 @@ export class UserVariables extends Construct {
this.sshKeyEnabled = process.env.SSH_KEY_ENABLED === "true";
this.cloudwatchDisabled = process.env.CLOUDWATCH_DISABLED === "true";
this.mqttKafkaTopicCreationDisabled = process.env.MQTT_KAFKA_TOPIC_CREATION_DISABLED === "true";
this.igwId = process.env.IGW_ID;
}
}

0 comments on commit db68ae8

Please sign in to comment.