def bootstrap(): click.echo('Starting bootstrap') click.echo('Starting regional deployments') all_regions = get_regions() with betterboto_client.MultiRegionClientContextManager( 'cloudformation', all_regions ) as clients: logger.info('Creating {}-regional'.format(constants.BOOTSTRAP_STACK_NAME)) threads = [] template = read_from_site_packages( '{}.template.yaml'.format('{}-regional'.format(constants.BOOTSTRAP_STACK_NAME)) ) template = Template(template).render(VERSION=constants.VERSION) args = { 'StackName': '{}-regional'.format(constants.BOOTSTRAP_STACK_NAME), 'TemplateBody': template, 'Capabilities': ['CAPABILITY_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': constants.VERSION, 'UsePreviousValue': False, }, ], } for client_region, client in clients.items(): process = Thread(name=client_region, target=client.create_or_update, kwargs=args) process.start() threads.append(process) for process in threads: process.join() logger.info('Finished creating {}-regional'.format(constants.BOOTSTRAP_STACK_NAME)) click.echo('Completed regional deployments') click.echo('Starting main deployment') s3_bucket_name = None with betterboto_client.ClientContextManager('cloudformation') as cloudformation: logger.info('Creating {}'.format(constants.BOOTSTRAP_STACK_NAME)) template = read_from_site_packages('{}.template.yaml'.format(constants.BOOTSTRAP_STACK_NAME)) template = Template(template).render(VERSION=constants.VERSION) args = { 'StackName': constants.BOOTSTRAP_STACK_NAME, 'TemplateBody': template, 'Capabilities': ['CAPABILITY_NAMED_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': constants.VERSION, 'UsePreviousValue': False, }, ], } cloudformation.create_or_update(**args) response = cloudformation.describe_stacks(StackName=constants.BOOTSTRAP_STACK_NAME) assert len(response.get('Stacks')) == 1, "Error code 1" stack_outputs = response.get('Stacks')[0]['Outputs'] for stack_output in stack_outputs: if stack_output.get('OutputKey') == 'CatalogBucketName': s3_bucket_name = stack_output.get('OutputValue') break logger.info( 'Finished creating {}. CatalogBucketName is: {}'.format( constants.BOOTSTRAP_STACK_NAME, s3_bucket_name ) ) logger.info('Adding empty product template to s3') template = open(resolve_from_site_packages('empty.template.yaml')).read() s3 = boto3.resource('s3') obj = s3.Object(s3_bucket_name, 'empty.template.yaml') obj.put(Body=template) logger.info('Finished adding empty product template to s3') logger.info('Finished bootstrap') with betterboto_client.ClientContextManager('codecommit') as codecommit: response = codecommit.get_repository(repositoryName=constants.SERVICE_CATALOG_FACTORY_REPO_NAME) clone_url = response.get('repositoryMetadata').get('cloneUrlHttp') clone_command = "git clone --config 'credential.helper=!aws codecommit " \ "credential-helper $@' --config 'credential.UseHttpPath=true' " \ "{}".format(clone_url) click.echo( 'You need to clone your newly created repo and then seed it: \n{}'.format( clone_command ) )
def _do_bootstrap(puppet_version, with_manual_approvals): click.echo('Starting bootstrap') ALL_REGIONS = get_regions(os.environ.get("AWS_DEFAULT_REGION")) with betterboto_client.MultiRegionClientContextManager( 'cloudformation', ALL_REGIONS) as clients: click.echo('Creating {}-regional'.format( constants.BOOTSTRAP_STACK_NAME)) threads = [] template = asset_helpers.read_from_site_packages( '{}.template.yaml'.format('{}-regional'.format( constants.BOOTSTRAP_STACK_NAME))) template = Template(template).render(VERSION=puppet_version) args = { 'StackName': '{}-regional'.format(constants.BOOTSTRAP_STACK_NAME), 'TemplateBody': template, 'Capabilities': ['CAPABILITY_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': puppet_version, 'UsePreviousValue': False, }, { 'ParameterKey': 'DefaultRegionValue', 'ParameterValue': os.environ.get('AWS_DEFAULT_REGION'), 'UsePreviousValue': False, }, ], 'Tags': [{ "Key": "ServiceCatalogPuppet:Actor", "Value": "Framework", }] } for client_region, client in clients.items(): process = Thread(name=client_region, target=client.create_or_update, kwargs=args) process.start() threads.append(process) for process in threads: process.join() click.echo('Finished creating {}-regional'.format( constants.BOOTSTRAP_STACK_NAME)) with betterboto_client.ClientContextManager( 'cloudformation') as cloudformation: click.echo('Creating {}'.format(constants.BOOTSTRAP_STACK_NAME)) template = asset_helpers.read_from_site_packages( '{}.template.yaml'.format(constants.BOOTSTRAP_STACK_NAME)) template = Template(template).render(VERSION=puppet_version, ALL_REGIONS=ALL_REGIONS) args = { 'StackName': constants.BOOTSTRAP_STACK_NAME, 'TemplateBody': template, 'Capabilities': ['CAPABILITY_NAMED_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': puppet_version, 'UsePreviousValue': False, }, { 'ParameterKey': 'OrgIamRoleArn', 'ParameterValue': str(get_org_iam_role_arn()), 'UsePreviousValue': False, }, { 'ParameterKey': 'WithManualApprovals', 'ParameterValue': "Yes" if with_manual_approvals else "No", 'UsePreviousValue': False, }, ], } cloudformation.create_or_update(**args) click.echo('Finished creating {}.'.format(constants.BOOTSTRAP_STACK_NAME)) with betterboto_client.ClientContextManager('codecommit') as codecommit: response = codecommit.get_repository( repositoryName=constants.SERVICE_CATALOG_PUPPET_REPO_NAME) clone_url = response.get('repositoryMetadata').get('cloneUrlHttp') clone_command = "git clone --config 'credential.helper=!aws codecommit credential-helper $@' " \ "--config 'credential.UseHttpPath=true' {}".format(clone_url) click.echo( 'You need to clone your newly created repo now and will then need to seed it: \n{}' .format(clone_command))
def bootstrap( puppet_account_id, with_manual_approvals, puppet_code_pipeline_role_permission_boundary, source_role_permissions_boundary, puppet_generate_role_permission_boundary, puppet_deploy_role_permission_boundary, puppet_provisioning_role_permissions_boundary, cloud_formation_deploy_role_permissions_boundary, deploy_environment_compute_type, spoke_deploy_environment_compute_type, deploy_num_workers, source_provider, owner, repo, branch, poll_for_source_changes, webhook_secret, puppet_role_name, puppet_role_path, scm_connection_arn, scm_full_repository_id, scm_branch_name, scm_bucket_name, scm_object_key, scm_skip_creation_of_repo, should_validate, custom_source_action_git_url, custom_source_action_git_web_hook_ip_address, custom_source_action_custom_action_type_version, custom_source_action_custom_action_type_provider, ): click.echo("Starting bootstrap") should_use_eventbridge = config.get_should_use_eventbridge( puppet_account_id, os.environ.get("AWS_DEFAULT_REGION") ) initialiser_stack_tags = config.get_initialiser_stack_tags() if should_use_eventbridge: with betterboto_client.ClientContextManager("events") as events: try: events.describe_event_bus(Name=constants.EVENT_BUS_NAME) except events.exceptions.ResourceNotFoundException: events.create_event_bus(Name=constants.EVENT_BUS_NAME,) all_regions = config.get_regions( puppet_account_id, os.environ.get("AWS_DEFAULT_REGION") ) with betterboto_client.MultiRegionClientContextManager( "cloudformation", all_regions ) as clients: click.echo("Creating {}-regional".format(constants.BOOTSTRAP_STACK_NAME)) threads = [] template = hub_bootstrap_region.get_template( constants.VERSION, os.environ.get("AWS_DEFAULT_REGION") ).to_yaml(clean_up=True) args = { "StackName": "{}-regional".format(constants.BOOTSTRAP_STACK_NAME), "TemplateBody": template, "Capabilities": ["CAPABILITY_IAM"], "Parameters": [ { "ParameterKey": "Version", "ParameterValue": constants.VERSION, "UsePreviousValue": False, }, { "ParameterKey": "DefaultRegionValue", "ParameterValue": os.environ.get("AWS_DEFAULT_REGION"), "UsePreviousValue": False, }, ], "Tags": [{"Key": "ServiceCatalogPuppet:Actor", "Value": "Framework",}] + initialiser_stack_tags, } for client_region, client in clients.items(): process = Thread( name=client_region, target=client.create_or_update, kwargs=args ) process.start() threads.append(process) for process in threads: process.join() click.echo( "Finished creating {}-regional".format(constants.BOOTSTRAP_STACK_NAME) ) source_args = {"Provider": source_provider} if source_provider == "CodeCommit": source_args.update( { "Configuration": { "RepositoryName": repo, "BranchName": branch, "PollForSourceChanges": poll_for_source_changes, }, } ) elif source_provider == "GitHub": source_args.update( { "Configuration": { "Owner": owner, "Repo": repo, "Branch": branch, "PollForSourceChanges": poll_for_source_changes, "SecretsManagerSecret": webhook_secret, }, } ) elif source_provider.lower() == "codestarsourceconnection": source_args.update( { "Configuration": { "ConnectionArn": scm_connection_arn, "FullRepositoryId": scm_full_repository_id, "BranchName": scm_branch_name, "OutputArtifactFormat": "CODE_ZIP", "DetectChanges": poll_for_source_changes, }, } ) elif source_provider.lower() == "s3": source_args.update( { "Configuration": { "S3Bucket": scm_bucket_name, "S3ObjectKey": scm_object_key, "PollForSourceChanges": poll_for_source_changes, }, } ) elif source_provider.lower() == "custom": source_args.update( { "Configuration": { "Owner": "Custom", "GitUrl": custom_source_action_git_url, "Branch": branch, "GitWebHookIpAddress": custom_source_action_git_web_hook_ip_address, "CustomActionTypeVersion": custom_source_action_custom_action_type_version, "CustomActionTypeProvider": custom_source_action_custom_action_type_provider, }, } ) template = hub_bootstrap.get_template( constants.VERSION, all_regions, source_args, config.is_caching_enabled( puppet_account_id, os.environ.get("AWS_DEFAULT_REGION") ), with_manual_approvals, scm_skip_creation_of_repo, should_validate, ).to_yaml(clean_up=True) args = { "StackName": constants.BOOTSTRAP_STACK_NAME, "TemplateBody": template, "Capabilities": ["CAPABILITY_NAMED_IAM"], "Parameters": [ { "ParameterKey": "Version", "ParameterValue": constants.VERSION, "UsePreviousValue": False, }, { "ParameterKey": "OrgIamRoleArn", "ParameterValue": str(config.get_org_iam_role_arn(puppet_account_id)), "UsePreviousValue": False, }, { "ParameterKey": "WithManualApprovals", "ParameterValue": "Yes" if with_manual_approvals else "No", "UsePreviousValue": False, }, { "ParameterKey": "PuppetCodePipelineRolePermissionBoundary", "ParameterValue": puppet_code_pipeline_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "SourceRolePermissionsBoundary", "ParameterValue": source_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetGenerateRolePermissionBoundary", "ParameterValue": puppet_generate_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetDeployRolePermissionBoundary", "ParameterValue": puppet_deploy_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetProvisioningRolePermissionsBoundary", "ParameterValue": puppet_provisioning_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "CloudFormationDeployRolePermissionsBoundary", "ParameterValue": cloud_formation_deploy_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "DeployEnvironmentComputeType", "ParameterValue": deploy_environment_compute_type, "UsePreviousValue": False, }, { "ParameterKey": "SpokeDeployEnvironmentComputeType", "ParameterValue": spoke_deploy_environment_compute_type, "UsePreviousValue": False, }, { "ParameterKey": "DeployNumWorkers", "ParameterValue": str(deploy_num_workers), "UsePreviousValue": False, }, { "ParameterKey": "PuppetRoleName", "ParameterValue": puppet_role_name, "UsePreviousValue": False, }, { "ParameterKey": "PuppetRolePath", "ParameterValue": puppet_role_path, "UsePreviousValue": False, }, ], "Tags": [{"Key": "ServiceCatalogPuppet:Actor", "Value": "Framework",}] + initialiser_stack_tags, } with betterboto_client.ClientContextManager("cloudformation") as cloudformation: click.echo("Creating {}".format(constants.BOOTSTRAP_STACK_NAME)) cloudformation.create_or_update(**args) buff = io.BytesIO() with zipfile.ZipFile(buff, mode="w", compression=zipfile.ZIP_DEFLATED) as z: z.writestr("parameters.yaml", 'single_account: "000000000000"') with betterboto_client.ClientContextManager("s3") as s3: try: s3.head_object( Bucket=f"sc-puppet-parameterised-runs-{puppet_account_id}", Key="parameters.zip", ) except botocore.exceptions.ClientError as ex: if ex.response["Error"]["Code"] == "404": s3.put_object( Bucket=f"sc-puppet-parameterised-runs-{puppet_account_id}", Key="parameters.zip", Body=buff.getvalue(), ) click.echo("Finished creating {}.".format(constants.BOOTSTRAP_STACK_NAME))
def _do_bootstrap( puppet_version, with_manual_approvals, puppet_code_pipeline_role_permission_boundary, source_role_permissions_boundary, puppet_generate_role_permission_boundary, puppet_deploy_role_permission_boundary, puppet_provisioning_role_permissions_boundary, cloud_formation_deploy_role_permissions_boundary, deploy_environment_compute_type="BUILD_GENERAL1_SMALL", deploy_num_workers=10, ): click.echo('Starting bootstrap') should_use_eventbridge = config.get_should_use_eventbridge(os.environ.get("AWS_DEFAULT_REGION")) if should_use_eventbridge: with betterboto_client.ClientContextManager('events') as events: try: events.describe_event_bus(Name=constants.EVENT_BUS_NAME) except events.exceptions.ResourceNotFoundException: events.create_event_bus( Name=constants.EVENT_BUS_NAME, ) all_regions = config.get_regions(os.environ.get("AWS_DEFAULT_REGION")) with betterboto_client.MultiRegionClientContextManager('cloudformation', all_regions) as clients: click.echo('Creating {}-regional'.format(constants.BOOTSTRAP_STACK_NAME)) threads = [] template = asset_helpers.read_from_site_packages( '{}.template.yaml'.format('{}-regional'.format(constants.BOOTSTRAP_STACK_NAME))) template = Template(template).render(VERSION=puppet_version) args = { 'StackName': '{}-regional'.format(constants.BOOTSTRAP_STACK_NAME), 'TemplateBody': template, 'Capabilities': ['CAPABILITY_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': puppet_version, 'UsePreviousValue': False, }, { 'ParameterKey': 'DefaultRegionValue', 'ParameterValue': os.environ.get('AWS_DEFAULT_REGION'), 'UsePreviousValue': False, }, ], 'Tags': [ { "Key": "ServiceCatalogPuppet:Actor", "Value": "Framework", } ] } for client_region, client in clients.items(): process = Thread(name=client_region, target=client.create_or_update, kwargs=args) process.start() threads.append(process) for process in threads: process.join() click.echo('Finished creating {}-regional'.format(constants.BOOTSTRAP_STACK_NAME)) with betterboto_client.ClientContextManager('cloudformation') as cloudformation: click.echo('Creating {}'.format(constants.BOOTSTRAP_STACK_NAME)) template = asset_helpers.read_from_site_packages('{}.template.yaml'.format(constants.BOOTSTRAP_STACK_NAME)) template = Template(template).render(VERSION=puppet_version, ALL_REGIONS=all_regions) args = { 'StackName': constants.BOOTSTRAP_STACK_NAME, 'TemplateBody': template, 'Capabilities': ['CAPABILITY_NAMED_IAM'], 'Parameters': [ { 'ParameterKey': 'Version', 'ParameterValue': puppet_version, 'UsePreviousValue': False, }, { 'ParameterKey': 'OrgIamRoleArn', 'ParameterValue': str(config.get_org_iam_role_arn()), 'UsePreviousValue': False, }, { 'ParameterKey': 'WithManualApprovals', 'ParameterValue': "Yes" if with_manual_approvals else "No", 'UsePreviousValue': False, }, { 'ParameterKey': 'PuppetCodePipelineRolePermissionBoundary', 'ParameterValue': puppet_code_pipeline_role_permission_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'SourceRolePermissionsBoundary', 'ParameterValue': source_role_permissions_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'PuppetGenerateRolePermissionBoundary', 'ParameterValue': puppet_generate_role_permission_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'PuppetDeployRolePermissionBoundary', 'ParameterValue': puppet_deploy_role_permission_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'PuppetProvisioningRolePermissionsBoundary', 'ParameterValue': puppet_provisioning_role_permissions_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'CloudFormationDeployRolePermissionsBoundary', 'ParameterValue': cloud_formation_deploy_role_permissions_boundary, 'UsePreviousValue': False, }, { 'ParameterKey': 'DeployEnvironmentComputeType', 'ParameterValue': deploy_environment_compute_type, 'UsePreviousValue': False, }, { 'ParameterKey': 'DeployNumWorkers', 'ParameterValue': str(deploy_num_workers), 'UsePreviousValue': False, }, ], } cloudformation.create_or_update(**args) click.echo('Finished creating {}.'.format(constants.BOOTSTRAP_STACK_NAME)) with betterboto_client.ClientContextManager('codecommit') as codecommit: response = codecommit.get_repository(repositoryName=constants.SERVICE_CATALOG_PUPPET_REPO_NAME) clone_url = response.get('repositoryMetadata').get('cloneUrlHttp') clone_command = "git clone --config 'credential.helper=!aws codecommit credential-helper $@' " \ "--config 'credential.UseHttpPath=true' {}".format(clone_url) click.echo( 'You need to clone your newly created repo now and will then need to seed it: \n{}'.format( clone_command ) )
def _do_bootstrap( puppet_version, puppet_account_id, with_manual_approvals, puppet_code_pipeline_role_permission_boundary, source_role_permissions_boundary, puppet_generate_role_permission_boundary, puppet_deploy_role_permission_boundary, puppet_provisioning_role_permissions_boundary, cloud_formation_deploy_role_permissions_boundary, deploy_environment_compute_type="BUILD_GENERAL1_SMALL", deploy_num_workers=10, source_provider=None, owner=None, repo=None, branch=None, poll_for_source_changes=None, webhook_secret=None, ): click.echo("Starting bootstrap") should_use_eventbridge = config.get_should_use_eventbridge( puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")) if should_use_eventbridge: with betterboto_client.ClientContextManager("events") as events: try: events.describe_event_bus(Name=constants.EVENT_BUS_NAME) except events.exceptions.ResourceNotFoundException: events.create_event_bus(Name=constants.EVENT_BUS_NAME, ) all_regions = config.get_regions(puppet_account_id, os.environ.get("AWS_DEFAULT_REGION")) with betterboto_client.MultiRegionClientContextManager( "cloudformation", all_regions) as clients: click.echo("Creating {}-regional".format( constants.BOOTSTRAP_STACK_NAME)) threads = [] template = asset_helpers.read_from_site_packages( "{}.template.yaml".format("{}-regional".format( constants.BOOTSTRAP_STACK_NAME))) template = Template(template).render(VERSION=puppet_version) args = { "StackName": "{}-regional".format(constants.BOOTSTRAP_STACK_NAME), "TemplateBody": template, "Capabilities": ["CAPABILITY_IAM"], "Parameters": [ { "ParameterKey": "Version", "ParameterValue": puppet_version, "UsePreviousValue": False, }, { "ParameterKey": "DefaultRegionValue", "ParameterValue": os.environ.get("AWS_DEFAULT_REGION"), "UsePreviousValue": False, }, ], "Tags": [{ "Key": "ServiceCatalogPuppet:Actor", "Value": "Framework", }], } for client_region, client in clients.items(): process = Thread(name=client_region, target=client.create_or_update, kwargs=args) process.start() threads.append(process) for process in threads: process.join() click.echo("Finished creating {}-regional".format( constants.BOOTSTRAP_STACK_NAME)) source_args = {"Provider": source_provider} if source_provider == "CodeCommit": source_args.update({ "Configuration": { "RepositoryName": repo, "BranchName": branch, }, }) elif source_provider == "GitHub": source_args.update({ "Configuration": { "Owner": owner, "Repo": repo, "Branch": branch, "PollForSourceChanges": poll_for_source_changes, "SecretsManagerSecret": webhook_secret, }, }) with betterboto_client.ClientContextManager( "cloudformation") as cloudformation: click.echo("Creating {}".format(constants.BOOTSTRAP_STACK_NAME)) template = asset_helpers.read_from_site_packages( "{}.template.yaml".format(constants.BOOTSTRAP_STACK_NAME)) template = Template(template).render(VERSION=puppet_version, ALL_REGIONS=all_regions, Source=source_args) template = Template(template).render(VERSION=puppet_version, ALL_REGIONS=all_regions, Source=source_args) args = { "StackName": constants.BOOTSTRAP_STACK_NAME, "TemplateBody": template, "Capabilities": ["CAPABILITY_NAMED_IAM"], "Parameters": [ { "ParameterKey": "Version", "ParameterValue": puppet_version, "UsePreviousValue": False, }, { "ParameterKey": "OrgIamRoleArn", "ParameterValue": str(config.get_org_iam_role_arn(puppet_account_id)), "UsePreviousValue": False, }, { "ParameterKey": "WithManualApprovals", "ParameterValue": "Yes" if with_manual_approvals else "No", "UsePreviousValue": False, }, { "ParameterKey": "PuppetCodePipelineRolePermissionBoundary", "ParameterValue": puppet_code_pipeline_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "SourceRolePermissionsBoundary", "ParameterValue": source_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetGenerateRolePermissionBoundary", "ParameterValue": puppet_generate_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetDeployRolePermissionBoundary", "ParameterValue": puppet_deploy_role_permission_boundary, "UsePreviousValue": False, }, { "ParameterKey": "PuppetProvisioningRolePermissionsBoundary", "ParameterValue": puppet_provisioning_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "CloudFormationDeployRolePermissionsBoundary", "ParameterValue": cloud_formation_deploy_role_permissions_boundary, "UsePreviousValue": False, }, { "ParameterKey": "DeployEnvironmentComputeType", "ParameterValue": deploy_environment_compute_type, "UsePreviousValue": False, }, { "ParameterKey": "DeployNumWorkers", "ParameterValue": str(deploy_num_workers), "UsePreviousValue": False, }, ], } cloudformation.create_or_update(**args) click.echo("Finished creating {}.".format(constants.BOOTSTRAP_STACK_NAME)) if source_provider == "CodeCommit": with betterboto_client.ClientContextManager( "codecommit") as codecommit: response = codecommit.get_repository(repositoryName=repo) clone_url = response.get("repositoryMetadata").get("cloneUrlHttp") clone_command = ( "git clone --config 'credential.helper=!aws codecommit credential-helper $@' " "--config 'credential.UseHttpPath=true' {}".format(clone_url)) click.echo( "You need to clone your newly created repo now and will then need to seed it: \n{}" .format(clone_command))