Exemple #1
0
    def __init__(self, scope: Construct, stack_id: str, *,
                 props: ServiceTierProps, **kwargs):
        """
        Initialize a new instance of ServiceTier
        :param scope: The scope of this construct.
        :param stack_id: The ID of this construct.
        :param props: The properties for this construct.
        :param kwargs: Any kwargs that need to be passed on to the parent class.
        """
        super().__init__(scope, stack_id, **kwargs)

        # Bastion instance for convenience (e.g. SSH into RenderQueue and WorkerFleet instances).
        # Not a critical component of the farm, so this can be safely removed. An alternative way
        # to access your hosts is also provided by the Session Manager, which is also configured
        # later in this example.
        self.bastion = BastionHostLinux(
            self,
            'Bastion',
            vpc=props.vpc,
            subnet_selection=SubnetSelection(
                subnet_group_name=subnets.PUBLIC.name),
            block_devices=[
                BlockDevice(device_name='/dev/xvda',
                            volume=BlockDeviceVolume.ebs(50, encrypted=True))
            ])

        # Mounting the root of the EFS file-system to the bastion access for convenience.
        # This can safely be removed.
        MountableEfs(self, filesystem=props.mountable_file_system.file_system
                     ).mount_to_linux_instance(self.bastion.instance,
                                               location='/mnt/efs')

        self.version = VersionQuery(self,
                                    'Version',
                                    version=props.deadline_version)

        secrets_management_settings = SecretsManagementProps(
            enabled=props.enable_secrets_management)
        if props.enable_secrets_management and props.secrets_management_secret_arn is not None:
            secrets_management_settings[
                "credentials"] = Secret.from_secret_arn(
                    self, 'SMAdminUser', props.secrets_management_secret_arn)

        repository = Repository(
            self,
            'Repository',
            vpc=props.vpc,
            vpc_subnets=SubnetSelection(
                subnet_group_name=subnets.INFRASTRUCTURE.name),
            database=props.database,
            file_system=props.mountable_file_system,
            repository_installation_timeout=Duration.minutes(20),
            repository_installation_prefix='/',
            version=self.version,
            secrets_management_settings=secrets_management_settings)

        images = ThinkboxDockerImages(
            self,
            'Images',
            version=self.version,
            user_aws_thinkbox_eula_acceptance=props.accept_aws_thinkbox_eula)

        server_cert = X509CertificatePem(
            self,
            'RQCert',
            subject=DistinguishedName(
                cn=f'renderqueue.{props.dns_zone.zone_name}',
                o='RFDK-Sample',
                ou='RenderQueueExternal'),
            signing_certificate=props.root_ca)

        self.render_queue = RenderQueue(
            self,
            'RenderQueue',
            vpc=props.vpc,
            vpc_subnets=SubnetSelection(
                subnet_group_name=subnets.INFRASTRUCTURE.name),
            # It is considered good practice to put the Render Queue's load blanacer in dedicated subnets because:
            #
            # 1. Deadline Secrets Management identity registration settings will be scoped down to least-privilege
            #
            #    (see https://github.com/aws/aws-rfdk/blob/release/packages/aws-rfdk/lib/deadline/README.md#render-queue-subnet-placement)
            #
            # 2. The load balancer can scale to use IP addresses in the subnet without conflicts from other AWS
            #    resources
            #
            #    (see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#subnets-load-balancer)
            vpc_subnets_alb=SubnetSelection(
                subnet_group_name=subnets.RENDER_QUEUE_ALB.name),
            images=images,
            repository=repository,
            hostname=RenderQueueHostNameProps(hostname='renderqueue',
                                              zone=props.dns_zone),
            traffic_encryption=RenderQueueTrafficEncryptionProps(
                external_tls=RenderQueueExternalTLSProps(
                    rfdk_certificate=server_cert),
                internal_protocol=ApplicationProtocol.HTTPS),
            version=self.version,
            # TODO - Evaluate deletion protection for your own needs. This is set to false to
            # cleanly remove everything when this stack is destroyed. If you would like to ensure
            # that this resource is not accidentally deleted, you should set this to true.
            deletion_protection=False,
            # Enable a local transparent filesystem cache of the Repository filesystem to reduce
            # data traffic from the Repository's filesystem.
            # For an EFS and NFS filesystem, this requires the 'fsc' mount option.
            enable_local_file_caching=True,
        )
        self.render_queue.connections.allow_default_port_from(self.bastion)

        # This is an optional feature that will set up your EC2 instances to be enabled for use with
        # the Session Manager. RFDK deploys EC2 instances that aren't available through a public subnet,
        # so connecting to them by SSH isn't easy. This is an option to quickly access hosts without
        # using a bastion instance.
        # It's important to note that the permissions need to be granted to the render queue's ASG,
        # rather than the render queue itself.
        SessionManagerHelper.grant_permissions_to(self.render_queue.asg)

        if props.ubl_licenses:
            if not props.ubl_certs_secret_arn:
                raise ValueError(
                    'UBL certificates secret ARN is required when using UBL but was not specified.'
                )
            ubl_cert_secret = Secret.from_secret_arn(
                self, 'ublcertssecret', props.ubl_certs_secret_arn)
            self.ubl_licensing = UsageBasedLicensing(
                self,
                'UsageBasedLicensing',
                vpc=props.vpc,
                vpc_subnets=SubnetSelection(
                    subnet_group_name=subnets.USAGE_BASED_LICENSING.name),
                images=images,
                licenses=props.ubl_licenses,
                render_queue=self.render_queue,
                certificate_secret=ubl_cert_secret,
            )

            # Another optional usage of the SessionManagerHelper that demonstrates how to configure the UBL
            # construct's ASG for access. Note that this construct also requires you to apply the permissions
            # to its ASG property.
            SessionManagerHelper.grant_permissions_to(self.ubl_licensing.asg)
        else:
            self.ubl_licensing = None
Exemple #2
0
    def __init__(self, scope: Construct, stack_id: str, *, props: SEPStackProps, **kwargs):
        """
        Initialize a new instance of SEPStack
        :param scope: The scope of this construct.
        :param stack_id: The ID of this construct.
        :param props: The properties for this construct.
        :param kwargs: Any kwargs that need to be passed on to the parent class.
        """
        super().__init__(scope, stack_id, **kwargs)

         # The VPC that all components of the render farm will be created in.
        vpc = Vpc(
            self,
            'Vpc',
            max_azs=2,
        )

        recipes = ThinkboxDockerRecipes(
            self,
            'Image',
            stage=Stage.from_directory(props.docker_recipes_stage_path),
        )

        repository = Repository(
            self,
            'Repository',
            vpc=vpc,
            version=recipes.version,
            repository_installation_timeout=Duration.minutes(20),
            # TODO - Evaluate deletion protection for your own needs. These properties are set to RemovalPolicy.DESTROY
            # to cleanly remove everything when this stack is destroyed. If you would like to ensure
            # that these resources are not accidentally deleted, you should set these properties to RemovalPolicy.RETAIN
            # or just remove the removal_policy parameter.
            removal_policy=RepositoryRemovalPolicies(
                database=RemovalPolicy.DESTROY,
                filesystem=RemovalPolicy.DESTROY,
            ),
        )

        host = 'renderqueue'
        zone_name = 'deadline-test.internal'

        # Internal DNS zone for the VPC.
        dns_zone = PrivateHostedZone(
            self,
            'DnsZone',
            vpc=vpc,
            zone_name=zone_name,
        )

        ca_cert = X509CertificatePem(
            self,
            'RootCA',
            subject=DistinguishedName(
                cn='SampleRootCA',
            ),
        )

        server_cert = X509CertificatePem(
            self,
            'RQCert',
            subject=DistinguishedName(
                cn=f'{host}.{dns_zone.zone_name}',
                o='RFDK-Sample',
                ou='RenderQueueExternal',
            ),
            signing_certificate=ca_cert,
        )

        render_queue = RenderQueue(
            self,
            'RenderQueue',
            vpc=vpc,
            version=recipes.version,
            images=recipes.render_queue_images,
            repository=repository,
            # TODO - Evaluate deletion protection for your own needs. This is set to false to
            # cleanly remove everything when this stack is destroyed. If you would like to ensure
            # that this resource is not accidentally deleted, you should set this to true.
            deletion_protection=False,
            hostname=RenderQueueHostNameProps(
                hostname=host,
                zone=dns_zone,
            ),
            traffic_encryption=RenderQueueTrafficEncryptionProps(
                external_tls=RenderQueueExternalTLSProps(
                    rfdk_certificate=server_cert,
                ),
                internal_protocol=ApplicationProtocol.HTTPS,
            ),
        )

        if props.create_resource_tracker_role:
            # Creates the Resource Tracker Access role. This role is required to exist in your account so the resource tracker will work properly
            Role(
                self,
                'ResourceTrackerRole',
                assumed_by=ServicePrincipal('lambda.amazonaws.com'),
                managed_policies= [ManagedPolicy.from_aws_managed_policy_name('AWSThinkboxDeadlineResourceTrackerAccessPolicy')],
                role_name= 'DeadlineResourceTrackerAccessRole',
            )

        fleet = SpotEventPluginFleet(
            self,
            'SpotEventPluginFleet',
            vpc=vpc,
            render_queue=render_queue,
            deadline_groups=['group_name'],
            instance_types=[InstanceType.of(InstanceClass.BURSTABLE3, InstanceSize.LARGE)],
            worker_machine_image=props.worker_machine_image,
            max_capacity=1,
        )

        # Optional: Add additional tags to both spot fleet request and spot instances.
        Tags.of(fleet).add('name', 'SEPtest')

        ConfigureSpotEventPlugin(
            self,
            'ConfigureSpotEventPlugin',
            vpc=vpc,
            render_queue=render_queue,
            spot_fleets=[fleet],
            configuration=SpotEventPluginSettings(
                enable_resource_tracker=True,
            ),
        )
Exemple #3
0
    def __init__(self, scope: Construct, stack_id: str, *,
                 props: ServiceTierProps, **kwargs):
        """
        Initialize a new instance of ServiceTier
        :param scope: The scope of this construct.
        :param stack_id: The ID of this construct.
        :param props: The properties for this construct.
        :param kwargs: Any kwargs that need to be passed on to the parent class.
        """
        super().__init__(scope, stack_id, **kwargs)

        # Bastion instance for convenience (e.g. SSH into RenderQueue and WorkerFleet instances).
        # Not a critical component of the farm, so this can be safely removed. An alternative way
        # to access your hosts is also provided by the Session Manager, which is also configured
        # later in this example.
        self.bastion = BastionHostLinux(
            self,
            'Bastion',
            vpc=props.vpc,
            subnet_selection=SubnetSelection(subnet_type=SubnetType.PUBLIC),
            block_devices=[
                BlockDevice(device_name='/dev/xvda',
                            volume=BlockDeviceVolume.ebs(50, encrypted=True))
            ])

        # Granting the bastion access to the file system mount for convenience.
        # This can also safely be removed.
        props.file_system.mount_to_linux_instance(self.bastion.instance,
                                                  location='/mnt/efs')

        recipes = ThinkboxDockerRecipes(self,
                                        'Image',
                                        stage=Stage.from_directory(
                                            props.docker_recipes_stage_path))

        repository = Repository(
            self,
            'Repository',
            vpc=props.vpc,
            database=props.database,
            file_system=props.file_system,
            repository_installation_timeout=Duration.minutes(20),
            version=recipes.version,
        )

        server_cert = X509CertificatePem(
            self,
            'RQCert',
            subject=DistinguishedName(
                cn=f'renderqueue.{props.dns_zone.zone_name}',
                o='RFDK-Sample',
                ou='RenderQueueExternal'),
            signing_certificate=props.root_ca)

        self.render_queue = RenderQueue(
            self,
            'RenderQueue',
            vpc=props.vpc,
            images=recipes.render_queue_images,
            repository=repository,
            hostname=RenderQueueHostNameProps(hostname='renderqueue',
                                              zone=props.dns_zone),
            traffic_encryption=RenderQueueTrafficEncryptionProps(
                external_tls=RenderQueueExternalTLSProps(
                    rfdk_certificate=server_cert),
                internal_protocol=ApplicationProtocol.HTTPS),
            version=recipes.version,
            # TODO - Evaluate deletion protection for your own needs. This is set to false to
            # cleanly remove everything when this stack is destroyed. If you would like to ensure
            # that this resource is not accidentally deleted, you should set this to true.
            deletion_protection=False)
        self.render_queue.connections.allow_default_port_from(self.bastion)

        # This is an optional feature that will set up your EC2 instances to be enabled for use with
        # the Session Manager. RFDK deploys EC2 instances that aren't available through a public subnet,
        # so connecting to them by SSH isn't easy. This is an option to quickly access hosts without
        # using a bastion instance.
        # It's important to note that the permissions need to be granted to the render queue's ASG,
        # rather than the render queue itself.
        SessionManagerHelper.grant_permissions_to(self.render_queue.asg)

        if props.ubl_licenses:
            if not props.ubl_certs_secret_arn:
                raise ValueError(
                    'UBL certificates secret ARN is required when using UBL but was not specified.'
                )
            ubl_cert_secret = Secret.from_secret_arn(
                self, 'ublcertssecret', props.ubl_certs_secret_arn)
            self.ubl_licensing = UsageBasedLicensing(
                self,
                'usagebasedlicensing',
                vpc=props.vpc,
                images=recipes.ubl_images,
                licenses=props.ubl_licenses,
                render_queue=self.render_queue,
                certificate_secret=ubl_cert_secret,
            )

            # Another optional usage of the SessionManagerHelper that demonstrates how to configure the UBL
            # construct's ASG for access. Note that this construct also requires you to apply the permissions
            # to its ASG property.
            SessionManagerHelper.grant_permissions_to(self.ubl_licensing.asg)
        else:
            self.ubl_licensing = None
Exemple #4
0
    def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps, **kwargs):
        """
        Initialize a new instance of ServiceTier
        :param scope: The scope of this construct.
        :param stack_id: The ID of this construct.
        :param props: The properties for this construct.
        :param kwargs: Any kwargs that need to be passed on to the parent class.
        """
        super().__init__(scope, stack_id, **kwargs)

        self.version = VersionQuery(
            self,
            'Version',
            version=props.deadline_version
        )

        # We are excluding the local zones from the Repository. This construct will create an
        # EFS filesystem and DocDB cluster, both of which aren't available in any local zones at this time.
        repository_subnets = SubnetSelection(
            availability_zones=props.availability_zones,
            subnet_type=SubnetType.PRIVATE
        )
        repository = Repository(
            self,
            'Repository',
            vpc=props.vpc,
            repository_installation_timeout=Duration.minutes(20),
            removal_policy=RepositoryRemovalPolicies(
                database=RemovalPolicy.DESTROY,
                filesystem=RemovalPolicy.DESTROY,
            ),
            version=self.version,
            vpc_subnets=repository_subnets
        )

        images = ThinkboxDockerImages(
            self,
            'Images',
            version=self.version,
            user_aws_thinkbox_eula_acceptance=props.accept_aws_thinkbox_eula
        )

        server_cert = X509CertificatePem(
            self,
            'RQCert',
            subject=DistinguishedName(
                cn=f'renderqueue.{props.dns_zone.zone_name}',
                o='RFDK-Sample',
                ou='RenderQueueExternal'
            ),
            signing_certificate=props.root_ca
        )

        # The render queue is also put only in the standard availability zones. The service itself
        # is run in a single zone, while the load balancer that sits in front of it can be provided
        # all the standard zones we're using.
        render_queue_subnets = SubnetSelection(
            availability_zones=[props.availability_zones[0]],
            subnet_type=SubnetType.PRIVATE
        )
        render_queue_alb_subnets = SubnetSelection(
            availability_zones=props.availability_zones,
            subnet_type=SubnetType.PRIVATE,
            one_per_az=True,
        )
        self.render_queue = RenderQueue(
            self,
            'RenderQueue',
            vpc=props.vpc,
            images=images,
            repository=repository,
            hostname=RenderQueueHostNameProps(
                hostname='renderqueue',
                zone=props.dns_zone
            ),
            traffic_encryption=RenderQueueTrafficEncryptionProps(
                external_tls=RenderQueueExternalTLSProps(
                    rfdk_certificate=server_cert
                ),
                internal_protocol=ApplicationProtocol.HTTPS
            ),
            version=self.version,
            vpc_subnets=render_queue_subnets,
            vpc_subnets_alb=render_queue_alb_subnets,
            deletion_protection=False
        )
        SessionManagerHelper.grant_permissions_to(self.render_queue.asg)
    def __init__(self, scope: Construct, stack_id: str, *,
                 props: ServiceTierProps, **kwargs):
        """
        Initialize a new instance of ServiceTier
        :param scope: The scope of this construct.
        :param stack_id: The ID of this construct.
        :param props: The properties for this construct.
        :param kwargs: Any kwargs that need to be passed on to the parent class.
        """
        super().__init__(scope, stack_id, **kwargs)

        # A bastion host to connect to the render farm with.
        # The bastion host is for convenience (e.g. SSH into RenderQueue and WorkerFleet instances).
        # This is not a critical component of the farm, so can safely be removed.
        self.bastion = BastionHostLinux(
            self,
            'Bastion',
            vpc=props.vpc,
            subnet_selection=SubnetSelection(subnet_type=SubnetType.PUBLIC),
            block_devices=[
                BlockDevice(device_name='/dev/xvda',
                            volume=BlockDeviceVolume.ebs(50, encrypted=True))
            ])

        # Granting the bastion access to the file system mount for convenience.
        # This can also safely be removed.
        props.file_system.mount_to_linux_instance(self.bastion.instance,
                                                  location='/mnt/efs')

        recipes = ThinkboxDockerRecipes(self,
                                        'Image',
                                        stage=Stage.from_directory(
                                            props.docker_recipes_stage_path))

        repository = Repository(
            self,
            'Repository',
            vpc=props.vpc,
            version=recipes.version,
            database=props.database,
            file_system=props.file_system,
            repository_installation_timeout=Duration.minutes(20))

        server_cert = X509CertificatePem(
            self,
            'RQCert',
            subject=DistinguishedName(
                cn=f'renderqueue.{props.dns_zone.zone_name}',
                o='RFDK-Sample',
                ou='RenderQueueExternal'),
            signing_certificate=props.root_ca)

        self.render_queue = RenderQueue(
            self,
            'RenderQueue',
            vpc=props.vpc,
            version=recipes.version,
            images=recipes.render_queue_images,
            repository=repository,
            hostname=RenderQueueHostNameProps(hostname='renderqueue',
                                              zone=props.dns_zone),
            traffic_encryption=RenderQueueTrafficEncryptionProps(
                external_tls=RenderQueueExternalTLSProps(
                    rfdk_certificate=server_cert),
                internal_protocol=ApplicationProtocol.HTTPS),
            # TODO - Evaluate deletion protection for your own needs. This is set to false to
            # cleanly remove everything when this stack is destroyed. If you would like to ensure
            # that this resource is not accidentally deleted, you should set this to true.
            deletion_protection=False)
        self.render_queue.connections.allow_default_port_from(self.bastion)

        if props.ubl_licenses:
            if not props.ubl_certs_secret_arn:
                raise ValueError(
                    'UBL certificates secret ARN is required when using UBL but was not specified.'
                )
            ubl_cert_secret = Secret.from_secret_arn(
                self, 'ublcertssecret', props.ubl_certs_secret_arn)
            self.ubl_licensing = UsageBasedLicensing(
                self,
                'usagebasedlicensing',
                vpc=props.vpc,
                images=recipes.ubl_images,
                licenses=props.ubl_licenses,
                render_queue=self.render_queue,
                certificate_secret=ubl_cert_secret,
            )