def rewrite_cfct()

in servicecatalog_puppet/manifest_utils.py [0:0]


def rewrite_cfct(manifest):
    manifest_accounts = dict()
    for account in manifest.get("accounts", []):
        if account.get("account_id"):
            manifest_accounts[account.get("name")] = account.get("account_id")

    prev = None
    for instance in manifest.get(constants.CFCT, []):
        if str(instance.get("version")) != "2021-03-15":
            raise Exception(
                f"not supported version of cfct manifest {instance.get('version')}"
            )
        default_region = instance.get("region")
        for resource in instance.get("resources", []):
            resource_file = resource.get("resource_file").lower()
            if resource_file.startswith("s3://"):
                m = re.match(r"s3://(.*)/(.*)", resource_file)
                bucket = m.group(1)
                key = m.group(2)
            elif resource_file.startswith("https://"):
                m = re.match(r"https://([a-z0-9-]+)(.*)/(.*)", resource_file)
                bucket = m.group(1)
                key = m.group(3)
            else:
                raise Exception(
                    f"All resource files should begin with s3:// of https://: {resource_file}"
                )

            name = resource.get("name")
            deploy_method = resource.get("deploy_method")

            if deploy_method == "stack_set":
                parameters = dict()
                depends_on = list()
                ssm = list()
                outputs = dict(ssm=ssm)
                deploy_to_accounts = list()
                deploy_to_tags = list()
                deploy_to = dict(tags=deploy_to_tags, accounts=deploy_to_accounts)

                if resource.get("parameter_file"):
                    parameter_file = resource.get("parameter_file")
                    if parameter_file.startswith("s3://"):
                        m = re.match(r"s3://(.*)/(.*)", parameter_file)
                        bucket = m.group(1)
                        key = m.group(2)
                    elif parameter_file.startswith("https://"):
                        m = re.match(r"https://([a-z0-9-]+)(.*)/(.*)", parameter_file)
                        bucket = m.group(1)
                        key = m.group(3)
                    else:
                        raise Exception(
                            f"All parameter_files should begin with s3:// of https://: {parameter_file}"
                        )
                    with betterboto_client.ClientContextManager("s3") as s3:
                        p = s3.get_object(Bucket=bucket, Key=key).read()
                        resource["parameters"] = json.loads(p)

                for p in resource.get("parameters", []):
                    parameter_key = p.get("parameter_key")
                    parameter_value = p.get("parameter_value")
                    m = re.match(r"\$\[alfred_ssm_(.*)\]", parameter_value)
                    if m:
                        parameters[parameter_key] = dict(
                            ssm=dict(name=m.group(1), region=default_region,)
                        )
                    else:
                        parameters[parameter_key] = dict(default=parameter_value)

                if prev is not None:
                    depends_on.append(
                        dict(name=prev, type=constants.STACK, affinity=constants.STACK,)
                    )

                for output in resource.get("export_outputs", []):
                    output_value = re.match(
                        r"\$\[output_(.*)\]", output.get("value")
                    ).group(1)
                    ssm.append(
                        dict(param_name=output.get("name"), stack_output=output_value)
                    )

                regions = resource.get("regions", [default_region])
                for account in resource.get("deployment_targets", {}).get(
                    "accounts", []
                ):
                    if re.match(r"[0-9]{12}", str(account)):
                        deploy_to_accounts.append(
                            dict(account_id=account, regions=regions)
                        )
                    else:
                        if manifest_accounts.get(account) is None:
                            raise Exception(
                                f"You are using CFCT resource: {name} to deploy to account: {account} which is not defined in your accounts section"
                            )
                        deploy_to_accounts.append(
                            dict(
                                account_id=manifest_accounts.get(account),
                                regions=regions,
                            )
                        )

                for organizational_unit in resource.get("deployment_targets", {}).get(
                    "organizational_units", []
                ):
                    deploy_to_tags.append(
                        dict(
                            tag=f"autogenerated:{organizational_unit}", regions=regions
                        )
                    )

                stack = dict(
                    name=name,
                    stack_set_name=name,
                    bucket=bucket,
                    key=key,
                    execution=constants.EXECUTION_MODE_HUB,
                    capabilities=["CAPABILITY_NAMED_IAM"],
                    parameters=parameters,
                    depends_on=depends_on,
                    outputs=outputs,
                    deploy_to=deploy_to,
                )

                if manifest.get(constants.STACKS) is None:
                    manifest[constants.STACKS] = dict()
                if manifest[constants.STACKS].get(name) is not None:
                    raise Exception(
                        f"You have a stack and a cfct resource with the same name: {name}"
                    )
                manifest[constants.STACKS][name] = stack

                prev = name

            elif deploy_method == "scp":
                with betterboto_client.ClientContextManager("s3") as s3:
                    p = s3.get_object(Bucket=bucket, Key=key).read()
                    content = json.loads(p)

                depends_on = list()
                deploy_to_accounts = list()
                deploy_to_ous = list()
                deploy_to = dict(accounts=deploy_to_accounts, ous=deploy_to_ous)

                if prev is not None:
                    depends_on.append(
                        dict(
                            name=prev,
                            type=constants.SERVICE_CONTROL_POLICY,
                            affinity=constants.SERVICE_CONTROL_POLICY,
                        )
                    )

                regions = "home_region"
                for account in resource.get("deployment_targets", {}).get(
                    "accounts", []
                ):
                    if re.match(r"[0-9]{12}", str(account)):
                        deploy_to_accounts.append(
                            dict(account_id=account, regions=regions)
                        )
                    else:
                        if manifest_accounts.get(account) is None:
                            raise Exception(
                                f"You are using CFCT resource: {name} to deploy to account: {account} which is not defined in your accounts section"
                            )
                        deploy_to_accounts.append(
                            dict(
                                account_id=manifest_accounts.get(account),
                                regions=regions,
                            )
                        )

                for organizational_unit in resource.get("deployment_targets", {}).get(
                    "organizational_units", []
                ):
                    deploy_to_ous.append(dict(ou=organizational_unit, regions=regions))

                scp = dict(
                    description=resource.get("description", "auto generated from CfCT"),
                    content=dict(default=content),
                    depends_on=depends_on,
                    apply_to=deploy_to,
                )

                if manifest.get(constants.SERVICE_CONTROL_POLICIES) is None:
                    manifest[constants.SERVICE_CONTROL_POLICIES] = dict()
                if manifest[constants.SERVICE_CONTROL_POLICIES].get(name) is not None:
                    raise Exception(
                        f"You have an SCP and a cfct resource with the same name: {name}"
                    )
                manifest[constants.SERVICE_CONTROL_POLICIES][name] = scp

                prev = name

            else:
                raise Exception(f"Unknown deploy_method of {deploy_method}")

    return manifest