Пример #1
0
def test_lookup(existing_cluster, nonexisting_cluster):
    """
    Function to test the dynamodb table lookup
    """
    here = path.abspath(path.dirname(__file__))
    session = boto3.session.Session()
    pill = placebo.attach(session, data_path=f"{here}/x_ecs")
    pill.playback()
    template = Template()
    stack = ComposeXStack("test", stack_template=template)
    settings = ComposeXSettings(
        content=existing_cluster,
        session=session,
        **{
            ComposeXSettings.name_arg: "test",
            ComposeXSettings.command_arg: ComposeXSettings.render_arg,
            ComposeXSettings.format_arg: "yaml",
        },
    )
    cluster = add_ecs_cluster(settings, stack)
    assert cluster is False

    template = Template()
    stack = ComposeXStack("test", stack_template=template)
    settings = ComposeXSettings(
        content=existing_cluster,
        session=session,
        **{
            ComposeXSettings.name_arg: "test",
            ComposeXSettings.command_arg: ComposeXSettings.render_arg,
            ComposeXSettings.format_arg: "yaml",
        },
    )
    cluster = add_ecs_cluster(settings, stack)
    assert cluster is True
Пример #2
0
def define_vpc_settings(settings: ComposeXSettings,
                        vpc_module: XResourceModule, vpc_stack: ComposeXStack):
    """
    Function to deal with vpc stack settings
    """
    if settings.requires_vpc() and not vpc_stack.vpc_resource:
        LOG.info(
            f"{settings.name} - Services or x-Resources need a VPC to function. Creating default one"
        )
        vpc_stack.create_new_default_vpc("vpc", vpc_module, settings)
        settings.root_stack.stack_template.add_resource(vpc_stack)
        vpc_stack.vpc_resource.generate_outputs()
    elif (vpc_stack.is_void and vpc_stack.vpc_resource
          and vpc_stack.vpc_resource.mappings):
        vpc_stack.vpc_resource.generate_outputs()
        add_update_mapping(
            settings.root_stack.stack_template,
            "Network",
            vpc_stack.vpc_resource.mappings,
        )
    elif (vpc_stack.vpc_resource and vpc_stack.vpc_resource.cfn_resource
          and vpc_stack.title
          not in settings.root_stack.stack_template.resources.keys()):
        settings.root_stack.stack_template.add_resource(vpc_stack)
        LOG.info(
            f"{settings.name}.x-vpc - VPC stack added. A new VPC will be created."
        )
        vpc_stack.vpc_resource.generate_outputs()
Пример #3
0
def add_spotfleet_stack(template, settings, launch_template):
    """
    Function to build the spotfleet stack and add it to the Cluster parent template

    :param launch_template: the launch template
    :param troposphere.Template template: parent cluster template
    :param ComposeXSettings settings: The settings for execution

    """
    compute_config = ComputeConfig(settings)
    parameters = {
        ROOT_STACK_NAME_T: If(
            cfn_conditions.USE_STACK_NAME_CON_T,
            Ref("AWS::StackName"),
            Ref(ROOT_STACK_NAME),
        ),
        compute_params.LAUNCH_TEMPLATE_ID_T: Ref(launch_template),
        compute_params.LAUNCH_TEMPLATE_VersionNumber_T: GetAtt(
            launch_template, "LatestVersionNumber"
        ),
        compute_params.MAX_CAPACITY_T: Ref(compute_params.MAX_CAPACITY),
        compute_params.MIN_CAPACITY_T: Ref(compute_params.MIN_CAPACITY),
        compute_params.TARGET_CAPACITY_T: Ref(compute_params.TARGET_CAPACITY),
    }
    fleet_template = generate_spot_fleet_template(settings, compute_config.spot_config)
    template.add_resource(
        ComposeXStack(
            "SpotFleet",
            stack_template=fleet_template,
            Condition=cfn_conditions.USE_SPOT_CON_T,
            Parameters=parameters,
        )
    )
Пример #4
0
def create_s3_template(new_buckets: list[Bucket],
                       template: Template) -> Template:
    """
    Function to create the root S3 template.

    :param list new_buckets:
    :param troposphere.Template template:
    :return:
    """
    mono_template = False
    if len(list(new_buckets)) <= COMPOSEX_MAX_OUTPUTS:
        mono_template = True

    for bucket in new_buckets:
        generate_bucket(bucket)
        if bucket.cfn_resource:
            bucket.init_outputs()
            bucket.generate_outputs()
            bucket_template = template
            if mono_template:
                bucket_template.add_resource(bucket.cfn_resource)
                bucket_template.add_output(bucket.outputs)
            elif not mono_template:
                bucket_template = build_template(
                    f"Template for S3 Bucket {bucket.name}")
                bucket_template.add_resource(bucket.cfn_resource)
                bucket_template.add_output(bucket.outputs)
                bucket_stack = ComposeXStack(bucket.logical_name,
                                             stack_template=bucket_template)
                template.add_resource(bucket_stack)
            evaluate_parameters(bucket, bucket_template)
    return template
Пример #5
0
def create_kms_template(template, new_keys, xstack):
    """
    Function to create all the KMS Keys based on their definition

    :param ecs_composex.common.settings.ComposeXSettings settings:
    """
    mono_template = False
    if len(new_keys) <= CFN_MAX_OUTPUTS:
        mono_template = True

    for key in new_keys:
        key.stack = xstack
        key.define_kms_key()
        if key and key.cfn_resource:
            key.init_outputs()
            key.generate_outputs()
            if mono_template:
                template.add_resource(key.cfn_resource)
                key.handle_key_settings(template)
                template.add_output(key.outputs)
            elif not mono_template:
                key_template = build_template(
                    f"Template for KMS key {key.logical_name}")
                key_template.add_resource(key.cfn_resource)
                key.handle_key_settings(key_template)
                key_template.add_output(key.outputs)
                key_stack = ComposeXStack(key.logical_name,
                                          stack_template=key_template)
                template.add_resource(key_stack)
Пример #6
0
def create_kms_template(settings):
    """

    :param ecs_composex.common.settings.ComposeXSettings settings:
    :return:
    """
    mono_template = False
    template = build_template("Root template for KMS")
    if not keyisset(RES_KEY, settings.compose_content):
        return
    keys = settings.compose_content[RES_KEY]
    if len(list(keys.keys())) <= CFN_MAX_OUTPUTS:
        mono_template = True

    for key_name in keys:
        key_res_name = NONALPHANUM.sub("", key_name)
        key = generate_key(key_name, key_res_name, keys[key_name])
        if key:
            values = [
                (KMS_KEY_ARN_T, "Arn", GetAtt(key, "Arn")),
                (KMS_KEY_ID_T, "Name", Ref(key)),
            ]
            outputs = ComposeXOutput(key, values, True)
            if mono_template:
                template.add_resource(key)
                handle_key_settings(template, key, keys[key_name])
                template.add_output(outputs.outputs)
            elif not mono_template:
                key_template = build_template(f"Template for DynamoDB key {key.title}")
                key_template.add_resource(key)
                key_template.add_output(outputs.outputs)
                key_stack = ComposeXStack(key_res_name, stack_template=key_template)
                template.add_resource(key_stack)
    return template
def create_dynamodb_template(new_tables, template, self_stack):
    """
    Function to create the root DynamdoDB template.

    :param list new_tables:
    :param troposhere.Template template:
    :param ComposeXStack self_stack:
    :return:
    """
    total_outputs = sum(
        len(table.attributes_outputs.keys()) for table in new_tables)
    mono_template = False
    if total_outputs <= CFN_MAX_OUTPUTS:
        mono_template = True
    for table in new_tables:
        if mono_template:
            table.stack = self_stack
            define_table(table, template)
        elif not mono_template:
            table_template = build_template(
                f"Template for DynamoDB table {table.title}")
            table_stack = ComposeXStack(table.logical_name,
                                        stack_template=table_template)
            table.stack = table_stack
            define_table(table, table_template)
            template.add_resource(table_stack)

    return template
Пример #8
0
def generate_sqs_root_template(settings):
    """
    Function to create the root DynamdoDB template.

    :param ecs_composex.common.settings.ComposeXSettings settings: Execution settings.
    :return:
    """
    mono_template = False
    output_per_resource = 2
    if not keyisset(RES_KEY, settings.compose_content):
        return None

    queues = settings.compose_content[RES_KEY]
    if (len(list(queues.keys())) * output_per_resource) <= CFN_MAX_OUTPUTS:
        mono_template = True
    template = build_template("DynamoDB for ECS ComposeX")
    for queue_name in queues:
        queue_res_name = NONALPHANUM.sub("", queue_name)
        queue_def = queues[queue_name]
        queue = define_queue(queue_name, queue_def, queues, mono_template)
        if queue:
            values = [
                (SQS_URL, "Url", Ref(queue)),
                (SQS_ARN_T, "Arn", GetAtt(queue, "Arn")),
                (SQS_NAME_T, "Name", Ref(queue)),
            ]
            outputs = ComposeXOutput(queue,
                                     values,
                                     duplicate_attr=(not mono_template))
            if mono_template:
                template.add_resource(queue)
                template.add_output(outputs.outputs)
            elif not mono_template:
                parameters = {}
                if hasattr(queue, "RedrivePolicy"):
                    parameters.update({
                        DLQ_ARN_T:
                        GetAtt(
                            NONALPHANUM.sub(
                                "",
                                queue_def["Properties"]["RedrivePolicy"]
                                ["deadLetterTargetArn"],
                            ),
                            f"Outputs.{SQS_ARN_T}",
                        )
                    })
                queue_template = build_template(
                    f"Template for SQS queue {queue.title}", [DLQ_ARN])
                queue_template.add_resource(queue)
                queue_template.add_output(outputs.outputs)
                queue_stack = ComposeXStack(
                    queue_res_name,
                    stack_template=queue_template,
                    stack_parameters=parameters,
                )
                template.add_resource(queue_stack)
    return template
Пример #9
0
def test_zone_create(content, zone_create):
    """
    Tests zone lookup
    :return:
    """
    print(content)
    updated_content = content.copy()
    updated_content.update(zone_create)
    settings = create_settings(updated_content, "x_dns")
    root_stack = ComposeXStack("root", build_template())
    DnsSettings(root_stack, settings, Ref("VpcId"))
Пример #10
0
def test_zone_lookup(content, zone_lookup):
    """
    Tests zone lookup
    :return:
    """
    updated_content = content.copy()
    updated_content.update(zone_lookup)
    settings = create_settings(updated_content, "x_dns")
    root_stack = ComposeXStack("root", build_template())
    try:
        DnsSettings(root_stack, settings, Ref("VpcId"))
    except Exception:
        pass
Пример #11
0
def render_new_queues(settings, new_queues, queues, xstack, template):
    """
    Function to create the root DynamdoDB template.

    :param ecs_composex.common.settings.ComposeXSettings settings: Execution settings.
    """
    mono_template = False
    output_per_resource = 3
    if (len(new_queues) * output_per_resource) <= CFN_MAX_OUTPUTS:
        mono_template = True

    for queue in new_queues:
        queue.stack = xstack
        define_queue(queue, queues, mono_template)
        if queue.cfn_resource:
            queue.init_outputs()
            queue.generate_outputs()
            if mono_template:
                template.add_resource(queue.cfn_resource)
                template.add_output(queue.outputs)
            elif not mono_template:
                parameters = {}
                if hasattr(queue, "RedrivePolicy"):
                    parameters.update({
                        DLQ_ARN_T:
                        GetAtt(
                            NONALPHANUM.sub(
                                "",
                                queues[queue.name].definition["Properties"]
                                ["RedrivePolicy"]["deadLetterTargetArn"],
                            ),
                            f"Outputs.{SQS_ARN_T}",
                        )
                    })
                queue_template = build_template(
                    f"Template for SQS queue {queue.cfn_resource.title}",
                    [DLQ_ARN],
                )
                queue_template.add_resource(queue.cfn_resource)
                queue_template.add_output(queue.outputs)
                queue_stack = ComposeXStack(
                    queue.logical_name,
                    stack_template=queue_template,
                    stack_parameters=parameters,
                )
                template.add_resource(queue_stack)
Пример #12
0
def create_root_stack(settings: ComposeXSettings) -> ComposeXStack:
    """
    Initializes the root stack template and ComposeXStack

    :param ecs_composex.common.settings.ComposeXSettings settings: The settings for the execution
    """
    template = init_template("Root template generated via ECS ComposeX")
    template.add_mapping("ComposeXDefaults",
                         {"ECS": {
                             "PlatformVersion": "1.4.0"
                         }})
    root_stack_title = NONALPHANUM.sub("", settings.name.title())
    root_stack = ComposeXStack(
        root_stack_title,
        stack_template=template,
        file_name=settings.name,
    )
    return root_stack
Пример #13
0
def add_certificates(acm_tpl, certs):
    """
    Function to add all the ACM certs together
    :param acm_tpl:
    :param certs:

    :return:
    """
    for cert_name in certs:
        resource_name = NONALPHANUM.sub("", cert_name)
        cert_def = certs[cert_name]
        cert_props = cert_def["Properties"]
        cert_params = build_cert_params(cert_props)
        cert_params.update(pass_root_stack_name())
        cert_template = initialize_acm_stack_template(resource_name)
        acm_tpl.add_resource(
            ComposeXStack(
                resource_name,
                stack_template=cert_template,
                Parameters=cert_params,
            ))
Пример #14
0
def generate_full_template(settings):
    """
    Function to generate the root root_template

    :param ecs_composex.common.settings.ComposeXSettings settings: The settings for the execution
    :return root_template: Template, params
    :rtype: root_template, list
    """
    LOG.debug(settings)
    root_stack = ComposeXStack(settings.name,
                               stack_template=init_root_template())
    dns_inputs(root_stack)
    vpc_stack = add_vpc_to_root(root_stack, settings)
    dns_settings = DnsSettings(root_stack, settings, get_vpc_id(vpc_stack))
    root_stack.Parameters.update(dns_settings.root_params)
    create_cluster = add_ecs_cluster(settings, root_stack)
    compute_stack = add_compute(root_stack.stack_template, settings, vpc_stack)
    if create_cluster and settings.create_compute and compute_stack:
        compute_stack.DependsOn.append(ROOT_CLUSTER_NAME)
    services_families = define_services_families(
        settings.compose_content[SERVICES_KEY])
    services_stack = create_services(root_stack, settings, vpc_stack,
                                     dns_settings.nested_params,
                                     create_cluster)
    add_x_resources(root_stack.stack_template, settings, vpc_stack=vpc_stack)
    apply_x_configs_to_ecs(settings, root_stack.stack_template, services_stack,
                           services_families)
    apply_x_to_x_configs(root_stack.stack_template, settings)

    if keyisset("x-appmesh", settings.compose_content):
        mesh = Mesh(
            settings.compose_content["x-appmesh"],
            services_families,
            services_stack,
            settings,
        )
        mesh.render_mesh_template(services_stack)
    add_all_tags(root_stack.stack_template, settings)
    return root_stack
Пример #15
0
def create_dynamodb_template(settings):
    """
    Function to create the root DynamdoDB template.

    :param ecs_composex.common.settings.ComposeXSettings settings:
    :return:
    """
    mono_template = False
    if not keyisset(RES_KEY, settings.compose_content):
        return None
    tables = settings.compose_content[RES_KEY]
    if len(list(tables.keys())) <= CFN_MAX_OUTPUTS:
        mono_template = True

    template = build_template("DynamoDB for ECS ComposeX")
    for table_name in tables:
        table_res_name = NONALPHANUM.sub("", table_name)
        table = generate_table(table_name, table_res_name, tables[table_name])
        if table:
            values = [
                (TABLE_ARN_T, "Arn", GetAtt(table, "Arn")),
                (TABLE_NAME_T, "Name", Ref(table)),
            ]
            outputs = ComposeXOutput(table, values, True)
            if mono_template:
                template.add_resource(table)
                template.add_output(outputs.outputs)
            elif not mono_template:
                table_template = build_template(
                    f"Template for DynamoDB table {table.title}"
                )
                table_template.add_resource(table)
                table_template.add_output(outputs.outputs)
                table_stack = ComposeXStack(
                    table_res_name, stack_template=table_template
                )
                template.add_resource(table_stack)
    return template
Пример #16
0
def add_sns_topics(root_template, content, res_count, count=170):
    """
    Function to add SNS topics to the root template

    :param int count: quantity of resources that should trigger the split into nested stacks
    :param root_template:
    :param content:
    :param int res_count: Number of resources created related to SNS
    :param kwargs:
    :return:
    """
    if res_count > count:
        LOG.info(
            f"There are more than {count} resources to handle for SNS. Splitting into nested stacks"
        )
        template = build_template("Root stack for SNS topics")
        add_topics_to_template(template, content[RES_KEY][TOPICS_KEY], content)
        add_topics_outputs(template)
        root_template.add_resource(
            ComposeXStack(title=TOPICS_STACK_NAME, stack_template=template)
        )
    else:
        add_topics_to_template(root_template, content[RES_KEY][TOPICS_KEY], content)
Пример #17
0
def add_db_stack(root_template, dbs_subnet_group, db_name, db, settings):
    """
    Function to add the DB stack to the root stack

    :param dbs_subnet_group: Subnet group for DBs
    :type dbs_subnet_group: troposphere.rds.DBSubnetGroup
    :param root_template: root template to add the nested stack to
    :type root_template: troposphere.Template
    :param db_name: name of the DB as defined in the x-rds section
    :type db_name: str
    :param db: the database definition from the compose file
    :type db: dict
    :param kwargs: extra arguments
    """
    props = db["Properties"]
    required_props = [DB_ENGINE_NAME_T, DB_ENGINE_VERSION_T]
    validate_kwargs(required_props, props)
    non_stack_params = {
        DB_ENGINE_NAME_T: props[DB_ENGINE_NAME_T],
        DB_ENGINE_VERSION_T: props[DB_ENGINE_VERSION_T],
    }
    parameters = {
        VPC_ID_T: Ref(VPC_ID),
        DBS_SUBNET_GROUP_T: Ref(dbs_subnet_group),
        DB_NAME_T: db_name,
        STORAGE_SUBNETS_T: Join(",", Ref(STORAGE_SUBNETS)),
        ROOT_STACK_NAME_T: Ref(ROOT_STACK_NAME),
    }
    parameters.update(non_stack_params)
    db_template = generate_database_template(db_name, db)
    if db_template is None:
        return
    db_stack = ComposeXStack(
        db_name, stack_template=db_template, stack_parameters=parameters
    )
    root_template.add_resource(db_stack)
Пример #18
0
def root_stack():
    tpl = Template("Template for testing")
    return ComposeXStack("root", stack_template=tpl)