Ejemplo n.º 1
0
def generate_tasks(f, single_account=None, is_dry_run=False):
    puppet_account_id = config.get_puppet_account_id()
    manifest = manifest_utils.load(f)

    should_use_sns = config.get_should_use_sns(os.environ.get("AWS_DEFAULT_REGION"))
    should_use_product_plans = config.get_should_use_product_plans(os.environ.get("AWS_DEFAULT_REGION"))

    tasks_to_run = manifest_utils_for_launches.generate_launch_tasks(
        manifest,
        puppet_account_id,
        should_use_sns,
        should_use_product_plans,
        include_expanded_from=False,
        single_account=single_account,
        is_dry_run=is_dry_run,
    )
    logger.info("Finished generating provisioning tasks")

    if not is_dry_run:
        logger.info("Generating sharing tasks")
        spoke_local_portfolios_tasks = manifest_utils_for_spoke_local_portfolios.generate_spoke_local_portfolios_tasks(
            manifest,
            puppet_account_id,
            should_use_sns,
            should_use_product_plans,
            include_expanded_from=False,
            single_account=single_account,
            is_dry_run=is_dry_run,
        )
        tasks_to_run += spoke_local_portfolios_tasks
        logger.info("Finished generating sharing tasks")

    logger.info("Finished generating all tasks")
    return tasks_to_run
def deploy(
    f,
    puppet_account_id,
    executor_account_id,
    single_account=None,
    num_workers=10,
    is_dry_run=False,
    is_list_launches=False,
    execution_mode="hub",
    on_complete_url=None,
    running_exploded=False,
):
    os.environ["SCT_CACHE_INVALIDATOR"] = str(datetime.now())
    os.environ["SCT_EXECUTION_MODE"] = str(execution_mode)
    os.environ["SCT_SINGLE_ACCOUNT"] = str(single_account)
    os.environ["SCT_IS_DRY_RUN"] = str(is_dry_run)
    os.environ["SCT_SHOULD_USE_SNS"] = str(
        config.get_should_use_sns(puppet_account_id))
    os.environ["SCT_SHOULD_USE_PRODUCT_PLANS"] = str(
        config.get_should_use_product_plans(
            puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")))
    tasks_to_run = generate_tasks(f, puppet_account_id, executor_account_id,
                                  execution_mode, is_dry_run)
    runner.run_tasks(
        puppet_account_id,
        executor_account_id,
        tasks_to_run,
        num_workers,
        is_dry_run,
        is_list_launches,
        execution_mode,
        on_complete_url,
        running_exploded,
    )
Ejemplo n.º 3
0
def generate_tasks(
    f,
    puppet_account_id,
    executor_account_id,
    single_account=None,
    is_dry_run=False,
    execution_mode="hub",
    cache_invalidator="now",
):
    should_use_sns = config.get_should_use_sns(
        puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")
    )
    should_use_product_plans = config.get_should_use_product_plans(
        puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")
    )

    return [
        launch_tasks.LaunchSectionTask(
            manifest_file_path=f.name,
            puppet_account_id=puppet_account_id,
            should_use_sns=should_use_sns,
            should_use_product_plans=should_use_product_plans,
            include_expanded_from=False,
            single_account=single_account,
            is_dry_run=is_dry_run,
            execution_mode=execution_mode,
            cache_invalidator=cache_invalidator,
        ),
        spoke_local_portfolios_tasks.SpokeLocalPortfolioSectionTask(
            manifest_file_path=f.name,
            puppet_account_id=puppet_account_id,
            should_use_sns=should_use_sns,
            should_use_product_plans=should_use_product_plans,
            include_expanded_from=False,
            single_account=single_account,
            is_dry_run=is_dry_run,
            execution_mode=execution_mode,
            cache_invalidator=cache_invalidator,
        ),
        lambda_invocations_tasks.LambdaInvocationsSectionTask(
            manifest_file_path=f.name,
            puppet_account_id=puppet_account_id,
            should_use_sns=should_use_sns,
            should_use_product_plans=should_use_product_plans,
            include_expanded_from=False,
            single_account=single_account,
            is_dry_run=is_dry_run,
            execution_mode=execution_mode,
            cache_invalidator=cache_invalidator,
        ),
    ]
Ejemplo n.º 4
0
def deploy(
    f,
    puppet_account_id,
    executor_account_id,
    single_account=None,
    num_workers=10,
    is_dry_run=False,
    is_list_launches=False,
    execution_mode="hub",
    on_complete_url=None,
    running_exploded=False,
    output_cache_starting_point="",
):
    if os.environ.get("SCT_CACHE_INVALIDATOR"):
        logger.info(
            f"Found existing SCT_CACHE_INVALIDATOR: {os.environ.get('SCT_CACHE_INVALIDATOR')}"
        )
    else:
        os.environ["SCT_CACHE_INVALIDATOR"] = str(datetime.now())

    os.environ["SCT_EXECUTION_MODE"] = str(execution_mode)
    os.environ["SCT_SINGLE_ACCOUNT"] = str(single_account)
    os.environ["SCT_IS_DRY_RUN"] = str(is_dry_run)
    os.environ["EXECUTOR_ACCOUNT_ID"] = str(executor_account_id)
    os.environ["SCT_SHOULD_USE_SNS"] = str(
        config.get_should_use_sns(puppet_account_id))
    os.environ["SCT_SHOULD_DELETE_ROLLBACK_COMPLETE_STACKS"] = str(
        config.get_should_delete_rollback_complete_stacks(puppet_account_id))
    os.environ["SCT_SHOULD_USE_PRODUCT_PLANS"] = str(
        config.get_should_use_product_plans(
            puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")))
    os.environ["SCT_INITIALISER_STACK_TAGS"] = json.dumps(
        config.get_initialiser_stack_tags())
    tasks_to_run = generate_tasks(f, puppet_account_id, executor_account_id,
                                  execution_mode, is_dry_run)
    runner.run_tasks(
        puppet_account_id,
        executor_account_id,
        tasks_to_run,
        num_workers,
        is_dry_run,
        is_list_launches,
        execution_mode,
        on_complete_url,
        running_exploded,
        output_cache_starting_point=output_cache_starting_point,
    )
Ejemplo n.º 5
0
def generate_tasks(f, single_account=None, dry_run=False):
    puppet_account_id = config.get_puppet_account_id()
    manifest = manifest_utils.load(f)
    tasks_to_run = []

    should_use_sns = config.get_should_use_sns(
        os.environ.get("AWS_DEFAULT_REGION"))
    should_use_product_plans = config.get_should_use_product_plans(
        os.environ.get("AWS_DEFAULT_REGION"))

    task_defs = manifest_utils.convert_manifest_into_task_defs_for_launches(
        manifest, puppet_account_id, should_use_sns, should_use_product_plans)

    for task in task_defs:
        if single_account is not None:
            if task.get('account_id') != single_account:
                continue
        task_status = task.get('status')
        del task['status']
        if task_status == constants.PROVISIONED:
            task['should_use_sns'] = should_use_sns
            if dry_run:
                tasks_to_run.append(
                    provisioning_tasks.ProvisionProductDryRunTask(**task))
            else:
                tasks_to_run.append(
                    provisioning_tasks.ProvisionProductTask(**task))
        elif task_status == constants.TERMINATED:
            for attribute in constants.DISALLOWED_ATTRIBUTES_FOR_TERMINATED_LAUNCHES:
                logger.info(
                    f"checking {task.get('launch_name')} for disallowed attributes"
                )
                attribute_value = task.get(attribute)
                if attribute_value is not None:
                    if isinstance(attribute_value, list):
                        if len(attribute_value) != 0:
                            raise Exception(
                                f"Launch {task.get('launch_name')} has disallowed attribute: {attribute}"
                            )
                    elif isinstance(attribute_value, dict):
                        if len(attribute_value.keys()) != 0:
                            raise Exception(
                                f"Launch {task.get('launch_name')} has disallowed attribute: {attribute}"
                            )
                    else:
                        raise Exception(
                            f"Launch {task.get('launch_name')} has disallowed attribute: {attribute}"
                        )

            del task['launch_parameters']
            del task['manifest_parameters']
            del task['account_parameters']
            del task['should_use_sns']
            del task['requested_priority']
            del task['should_use_product_plans']
            del task['pre_actions']
            del task['post_actions']

            if dry_run:
                tasks_to_run.append(
                    provisioning_tasks.TerminateProductDryRunTask(**task))
            else:
                tasks_to_run.append(
                    provisioning_tasks.TerminateProductTask(**task))
        else:
            raise Exception(f"Unsupported status of {task_status}")

    if not dry_run:
        spoke_local_portfolios_tasks = manifest_utils.convert_manifest_into_task_defs_for_spoke_local_portfolios(
            manifest, puppet_account_id, should_use_sns, tasks_to_run)
        for spoke_local_portfolios_task in spoke_local_portfolios_tasks:
            if single_account is not None:
                param_kwargs = spoke_local_portfolios_task.param_kwargs
                logger.info(f"EPF:: {param_kwargs}")
                if param_kwargs.get('account_id',
                                    'not_an_account_id') != single_account:
                    continue
            tasks_to_run.append(spoke_local_portfolios_task)
    return tasks_to_run
Ejemplo n.º 6
0
def expand(f, puppet_account_id, single_account, subset=None):
    click.echo("Expanding")
    manifest = manifest_utils.load(f, puppet_account_id)
    org_iam_role_arn = config.get_org_iam_role_arn(puppet_account_id)
    if org_iam_role_arn is None:
        click.echo("No org role set - not expanding")
        new_manifest = manifest
    else:
        click.echo("Expanding using role: {}".format(org_iam_role_arn))
        with betterboto_client.CrossAccountClientContextManager(
            "organizations", org_iam_role_arn, "org-iam-role"
        ) as client:
            new_manifest = manifest_utils.expand_manifest(manifest, client)
    click.echo("Expanded")
    if single_account:
        click.echo(f"Filtering for single account: {single_account}")

        for account in new_manifest.get("accounts", []):
            if str(account.get("account_id")) == str(single_account):
                click.echo(f"Found single account: {single_account}")
                new_manifest["accounts"] = [account]
                break

        click.echo("Filtered")

    new_manifest = manifest_utils.rewrite_depends_on(new_manifest)
    new_manifest = manifest_utils.rewrite_ssm_parameters(new_manifest)
    new_manifest = manifest_utils.rewrite_stacks(new_manifest, puppet_account_id)

    if subset:
        click.echo(f"Filtering for subset: {subset}")
        new_manifest = manifest_utils.isolate(
            manifest_utils.Manifest(new_manifest), subset
        )

    new_manifest = json.loads(json.dumps(new_manifest))

    if new_manifest.get(constants.LAMBDA_INVOCATIONS) is None:
        new_manifest[constants.LAMBDA_INVOCATIONS] = dict()

    home_region = config.get_home_region(puppet_account_id)
    with betterboto_client.ClientContextManager("ssm") as ssm:
        response = ssm.get_parameter(Name="service-catalog-puppet-version")
        version = response.get("Parameter").get("Value")

    new_manifest["config_cache"] = dict(
        home_region=home_region,
        regions=config.get_regions(puppet_account_id, home_region),
        should_collect_cloudformation_events=config.get_should_use_sns(
            puppet_account_id, home_region
        ),
        should_forward_events_to_eventbridge=config.get_should_use_eventbridge(
            puppet_account_id, home_region
        ),
        should_forward_failures_to_opscenter=config.get_should_forward_failures_to_opscenter(
            puppet_account_id, home_region
        ),
        puppet_version=version,
    )

    new_name = f.name.replace(".yaml", "-expanded.yaml")
    logger.info("Writing new manifest: {}".format(new_name))
    with open(new_name, "w") as output:
        output.write(yaml.safe_dump(new_manifest, default_flow_style=False))
Ejemplo n.º 7
0
def expand(f, puppet_account_id, single_account, subset=None):
    click.echo("Expanding")
    target_directory = os.path.sep.join([os.path.dirname(f.name), "manifests"])
    assemble_manifest_from_ssm(target_directory)
    manifest = manifest_utils.load(f, puppet_account_id)
    org_iam_role_arn = config.get_org_iam_role_arn(puppet_account_id)
    if org_iam_role_arn is None:
        click.echo("No org role set - not expanding")
        new_manifest = manifest
    else:
        click.echo("Expanding using role: {}".format(org_iam_role_arn))
        with betterboto_client.CrossAccountClientContextManager(
            "organizations", org_iam_role_arn, "org-iam-role"
        ) as client:
            new_manifest = manifest_utils.expand_manifest(manifest, client)
    click.echo("Expanded")

    new_manifest = manifest_utils.rewrite_deploy_as_share_to_for_spoke_local_portfolios(
        new_manifest
    )
    if single_account:
        click.echo(f"Filtering for single account: {single_account}")

        for account in new_manifest.get("accounts", []):
            if str(account.get("account_id")) == str(single_account):
                click.echo(f"Found single account: {single_account}")
                new_manifest["accounts"] = [account]
                break

        items_to_delete = list()
        for section_name in constants.ALL_SECTION_NAMES:
            deploy_to_name = constants.DEPLOY_TO_NAMES[section_name]
            for item_name, item in new_manifest.get(section_name, {}).items():
                accounts = list()
                for deploy_details in item.get(deploy_to_name, {}).get("accounts", []):
                    if str(deploy_details.get("account_id")) == str(single_account):
                        accounts.append(deploy_details)

                print(f"{item_name}: there are " + str(len(accounts)))
                if item.get(deploy_to_name).get("accounts"):
                    if len(accounts) > 0:
                        item[deploy_to_name]["accounts"] = accounts
                    else:
                        if item[deploy_to_name].get("tags") or item[deploy_to_name].get(
                            "ous"
                        ):
                            del item[deploy_to_name]["accounts"]
                        else:
                            items_to_delete.append(f"{section_name}:{item_name}")
        for item_to_delete in items_to_delete:
            section_name, item_name = item_to_delete.split(":")
            del new_manifest[section_name][item_name]

        click.echo("Filtered")

    new_manifest = manifest_utils.rewrite_cfct(new_manifest)
    new_manifest = manifest_utils.rewrite_depends_on(new_manifest)
    new_manifest = manifest_utils.rewrite_ssm_parameters(new_manifest)
    new_manifest = manifest_utils.rewrite_stacks(new_manifest, puppet_account_id)
    new_manifest = manifest_utils.rewrite_scps(new_manifest, puppet_account_id)
    new_manifest = manifest_utils.parse_conditions(new_manifest)

    if subset and subset.get("section"):
        click.echo(f"Filtering for subset: {subset}")
        new_manifest = manifest_utils.isolate(new_manifest, subset)

    manifest_accounts_all = [
        {"account_id": a.get("account_id"), "email": a.get("email")}
        for a in new_manifest.get("accounts", [])
    ]
    manifest_accounts_excluding = [
        a for a in manifest_accounts_all if a.get("account_id") != puppet_account_id
    ]

    # handle all accounts
    sct_manifest_accounts = json.dumps(manifest_accounts_all)
    sct_manifest_spokes = json.dumps(manifest_accounts_excluding)
    regions = config.get_regions(puppet_account_id)
    sct_config_regions = json.dumps(regions)

    new_manifest["parameters"]["SCTManifestAccounts"] = dict(
        default=sct_manifest_accounts
    )
    new_manifest["parameters"]["SCTManifestSpokes"] = dict(default=sct_manifest_spokes)
    new_manifest["parameters"]["SCTConfigRegions"] = dict(default=sct_config_regions)
    new_manifest["parameters"]["SCTAccountId"] = dict(default=puppet_account_id)

    if new_manifest.get(constants.LAMBDA_INVOCATIONS) is None:
        new_manifest[constants.LAMBDA_INVOCATIONS] = dict()

    home_region = config.get_home_region(puppet_account_id)
    with betterboto_client.ClientContextManager("ssm") as ssm:
        response = ssm.get_parameter(Name="service-catalog-puppet-version")
        version = response.get("Parameter").get("Value")

    new_manifest["config_cache"] = dict(
        home_region=home_region,
        regions=regions,
        should_collect_cloudformation_events=config.get_should_use_sns(
            puppet_account_id, home_region
        ),
        should_forward_events_to_eventbridge=config.get_should_use_eventbridge(
            puppet_account_id, home_region
        ),
        should_forward_failures_to_opscenter=config.get_should_forward_failures_to_opscenter(
            puppet_account_id, home_region
        ),
        puppet_version=version,
    )

    new_name = f.name.replace(".yaml", "-expanded.yaml")
    logger.info("Writing new manifest: {}".format(new_name))
    with open(new_name, "w") as output:
        output.write(yaml_utils.dump(new_manifest))
Ejemplo n.º 8
0
def run_tasks_for_generate_shares(tasks_to_run):
    for type in [
            "failure",
            "success",
            "timeout",
            "process_failure",
            "processing_time",
            "broken_task",
    ]:
        os.makedirs(Path(constants.RESULTS_DIRECTORY) / type)

    run_result = luigi.build(
        tasks_to_run,
        local_scheduler=True,
        detailed_summary=True,
        workers=10,
        log_level='INFO',
    )

    should_use_sns = config.get_should_use_sns()
    puppet_account_id = config.get_puppet_account_id()
    version = config.get_puppet_version()

    for region in config.get_regions():
        sharing_policies = {
            'accounts': [],
            'organizations': [],
        }
        with betterboto_client.ClientContextManager(
                'cloudformation', region_name=region) as cloudformation:
            cloudformation.ensure_deleted(
                StackName="servicecatalog-puppet-shares")

            logger.info(f"generating policies collection for region {region}")
            if os.path.exists(os.path.sep.join(['data', 'bucket'])):
                logger.info(f"Updating policies for the region: {region}")
                path = os.path.sep.join(['data', 'bucket', region, 'accounts'])
                if os.path.exists(path):
                    for account_file in os.listdir(path):
                        account = account_file.split(".")[0]
                        sharing_policies['accounts'].append(account)

                path = os.path.sep.join(
                    ['data', 'bucket', region, 'organizations'])
                if os.path.exists(path):
                    for organization_file in os.listdir(path):
                        organization = organization_file.split(".")[0]
                        sharing_policies['organizations'].append(organization)

            logger.info(f"Finished generating policies collection")

            template = config.env.get_template(
                'policies.template.yaml.j2').render(
                    sharing_policies=sharing_policies,
                    VERSION=version,
                )
            with betterboto_client.ClientContextManager(
                    'cloudformation', region_name=region) as cloudformation:
                cloudformation.create_or_update(
                    StackName="servicecatalog-puppet-policies",
                    TemplateBody=template,
                    NotificationARNs=[
                        f"arn:aws:sns:{region}:{puppet_account_id}:servicecatalog-puppet-cloudformation-regional-events"
                    ] if should_use_sns else [],
                )

    for filename in glob('results/failure/*.json'):
        result = json.loads(open(filename, 'r').read())
        click.echo(
            colorclass.Color("{red}" + result.get('task_type') +
                             " failed{/red}"))
        click.echo(
            f"{yaml.safe_dump({'parameters':result.get('task_params')})}")
        click.echo("\n".join(result.get('exception_stack_trace')))
        click.echo('')
    exit_status_codes = {
        LuigiStatusCode.SUCCESS: 0,
        LuigiStatusCode.SUCCESS_WITH_RETRY: 0,
        LuigiStatusCode.FAILED: 1,
        LuigiStatusCode.FAILED_AND_SCHEDULING_FAILED: 2,
        LuigiStatusCode.SCHEDULING_FAILED: 3,
        LuigiStatusCode.NOT_RUN: 4,
        LuigiStatusCode.MISSING_EXT: 5,
    }
    sys.exit(exit_status_codes.get(run_result.status))