def __init__()

in swarm_cdk/swarm_cdk_deployment.py [0:0]


    def __init__(self, scope: core.Construct, id: str, bucket, vpc, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        publicsubnets = vpc.select_subnets(subnet_type=ec2.SubnetType.PUBLIC)
        privatesubnets = vpc.select_subnets(subnet_type=ec2.SubnetType.PRIVATE)

        # Custom policy to allow writes to S3 bucket for 
        
        writelogspolicy = iam.PolicyStatement(
            effect=iam.Effect.ALLOW,
            actions=["s3:GetObject",],
            resources=[bucket.bucket_arn+ "/*"]
        )

        writelogsdocument = iam.PolicyDocument()
        writelogsdocument.add_statements(writelogspolicy)

        # Instance Role and SSM Managed Policy
        role = iam.Role(self, "SwarmInstanceRole", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"), inline_policies=[writelogsdocument])

        role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AmazonSSMManagedInstanceCore"))
        role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("EC2InstanceProfileForImageBuilder"))

        # Create instance profile that EC2 Image builder can use
        # This can be also later used running Swarm instances
        instanceprofile = iam.CfnInstanceProfile(self, "InstanceProfile",
            instance_profile_name="ue4-swarm-instance-profile",
            path="/executionServiceEC2Role/",
            roles=[role.role_name]
        )

        # Security Group for the Swarm instances that allows communication
        securitygroup = ec2.SecurityGroup(self, "SecurityGroup",
            vpc=vpc,
            description="Security Group for UE4 Swarm",
            security_group_name="Allow UE4 Swarm communication",
            allow_all_outbound=True
            )


        # Allow Swarm Agents and Coordinator to talk to each other in same Security Group
        securitygroup.add_ingress_rule(securitygroup, ec2.Port.tcp_range(8008,8009), 'Allow SG Swarm TCP')
        securitygroup.add_ingress_rule(securitygroup, ec2.Port.icmp_ping(), 'Allow SG Swarm ICMP Ping')

        # Parameter for the trusted network
        trusted_cidr = self.node.try_get_context("trusted_cidr")

        # Define default trusted CIDR
        if trusted_cidr is None:
            trusted_cidr = "10.0.0.0/8"

        # Allow RDP, Swarm and ICMP ping from trusted CIDR prefix
        securitygroup.add_ingress_rule(ec2.Peer.ipv4(trusted_cidr), ec2.Port.tcp_range(8008,8009), 'Allow Trusted IP Swarm TCP')
        securitygroup.add_ingress_rule(ec2.Peer.ipv4(trusted_cidr), ec2.Port.icmp_ping(), 'Allow Trusted IP Swarm ICMP Ping')
        securitygroup.add_ingress_rule(ec2.Peer.ipv4(trusted_cidr), ec2.Port.tcp(3389), 'Allow Trusted IP RDP TCP')

        # Read the EC2 Image builder component instructions from a file
        # These instructions are PowerShell commands to download dependencies ZIP.
        # It will then uncompress it, run nessesary installations for the components.

        component_file_path = "assets/component.yml"
        image_builder_instance_type = ["m5.large"]

        with open(component_file_path, 'r') as componentfile:
            componentdata = componentfile.read()

        componentdata = componentdata.replace("S3-BUCKET-NAME", bucket.bucket_name)

        # Define the component for EC2 Image Builder
        swarmcomponent = imagebuilder.CfnComponent(self,
            "SwarmComponent",
            name="Install-Swarm-Dependencies",
            platform="Windows",
            version="1.0.0",
            data=componentdata
        ) 

        # Define the new VPC and Instanceprofile to be used for Image Building
        infraconfig = imagebuilder.CfnInfrastructureConfiguration(self,
            "SwarmInfraConfig",
            name="UE4-Swarm-WindowsServer-2019-Infra-Config",
            instance_profile_name=instanceprofile.instance_profile_name,
            # logging=imagebuilder.CfnInfrastructureConfiguration.S3LogsProperty(s3_bucket_name=bucket.bucket_name),
            subnet_id=privatesubnets.subnets[0].subnet_id,
            security_group_ids=[securitygroup.security_group_id],
            instance_types=image_builder_instance_type
        )

        # Ensure that instance profile has completed creation before applying the aboce config
        infraconfig.add_depends_on(instanceprofile)

        # Lookup latest Windows Server 2019
        basewindows = ec2.MachineImage.latest_windows(ec2.WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE);

        # Define Image build recipe combinen the Windows image and our Component
        recipe = imagebuilder.CfnImageRecipe(self,
            "ImageRecipe",
            name="UE4-Swarm-Image",
            parent_image=basewindows.get_image(self).image_id,
            version="1.0.0",
            components=[{"componentArn":swarmcomponent.attr_arn}]
        )

        # Start the build of new AMI based on the Recipe and Infra config
        swarmimage = imagebuilder.CfnImage(self,
            "SwarmImage",
            image_recipe_arn=recipe.attr_arn,
            infrastructure_configuration_arn=infraconfig.attr_arn
            )

        # Lookup the AMI ID for the resulting image
        swarmami = ec2.GenericWindowsImage({self.region: swarmimage.attr_image_id})

        # Read the Script to start Swarm Coordinator
        # Will be used in the instance user data
        with open('assets/start-coordinator.ps1', 'r') as coordfile:
            coorduserdata = coordfile.read()

        # Parameter for the instance type
        coordinator_instancy_type = self.node.try_get_context("coordinator_instancy_type")

        # Define default instance type
        if coordinator_instancy_type is None:
            coordinator_instancy_type = "t3.large"

        # Launch the Swarm Coordinator instance
        coordinator = ec2.Instance(self, "ue4-swarm-coordinator",
            instance_type=ec2.InstanceType(coordinator_instancy_type),
            machine_image=swarmami,
            vpc = vpc,
            vpc_subnets = ec2.SubnetSelection(subnet_type=ec2.SubnetType('PRIVATE')),
            role = role,
            security_group=securitygroup,
            user_data=ec2.UserData.custom(coorduserdata)
            )

        with open('assets/start-agent.ps1', 'r') as agentfile:
            agentuserdata = agentfile.read()

        agentuserdata = agentuserdata.replace("COORDINATOR_IP", coordinator.instance_private_ip)

        # Define C: -drives size for the Swarm Agents
        root_device = autoscaling.BlockDevice(
            device_name='/dev/sda1',
            volume=autoscaling.BlockDeviceVolume.ebs(
                volume_size=100,
                delete_on_termination=True
            ),
        )

        # Parameter for the instance type
        agent_instancy_type = self.node.try_get_context("agent_instancy_type")

        # Define default instance type
        if agent_instancy_type is None:
            agent_instancy_type = "t3.xlarge"

        # Create Autoscaling group for Swarm Agents
        # It won't automaticaly scale on load but instead it will automatically
        # Scale down at evening and bring the cluster up again in the morning
        swarmasg = autoscaling.AutoScalingGroup(self, "ue4-swarm-agent",
            instance_type=ec2.InstanceType(agent_instancy_type),
            machine_image=swarmami,
            role=role,
            vpc=vpc,
            vpc_subnets = ec2.SubnetSelection(subnet_type=ec2.SubnetType('PRIVATE')),
            security_group=securitygroup,
            block_devices=[root_device],
            user_data=ec2.UserData.custom(agentuserdata),
            desired_capacity=1,
            max_capacity=1,
            min_capacity=1)


        # Output the AMI ID and Coordinator IP
        output = core.CfnOutput(self, "ImageID",
                                value=swarmimage.attr_image_id,
                                description="Swarm AMI ID")

        output = core.CfnOutput(self, "CoordinatorPrivateIP",
                                value=coordinator.instance_private_ip,
                                description="Coordinator Instance Private IP")