def get_initialiser_stack_tags(): with betterboto_client.ClientContextManager("ssm") as ssm: try: response = ssm.get_parameter( Name=constants.INITIALISER_STACK_NAME_SSM_PARAMETER) initialiser_stack_name = response.get("Parameter").get("Value") with betterboto_client.ClientContextManager( "cloudformation") as cloudformation: paginator = cloudformation.get_paginator("describe_stacks") for page in paginator.paginate( StackName=initialiser_stack_name, ): for stack in page.get("Stacks", []): if stack.get("StackStatus") in [ "CREATE_IN_PROGRESS", "CREATE_COMPLETE", "UPDATE_IN_PROGRESS", "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS", "UPDATE_COMPLETE", ]: return stack.get("Tags") else: raise Exception( f"Initialiser stack: {initialiser_stack_name} in state: {stack.get('StackStatus')}" ) except ssm.exceptions.ParameterNotFound: logger.warning( f"Could not find SSM parameter: {constants.INITIALISER_STACK_NAME_SSM_PARAMETER}, do not know the tags to use" ) return []
def run(self): with betterboto_client.ClientContextManager( "servicecatalog", region_name=self.region ) as service_catalog: self.info(f"Looking for product to delete: {self.name}") search_products_as_admin_response = service_catalog.search_products_as_admin_single_page( Filters={"FullTextSearch": [self.name]} ) found_product = False for product_view_details in search_products_as_admin_response.get( "ProductViewDetails" ): product_view_summary = product_view_details.get("ProductViewSummary") if product_view_summary.get("Name") == self.name: found_product = True product_id = product_view_summary.get("ProductId") logger.info(f"Found product: {self.name}: {product_view_summary}") break if found_product: with betterboto_client.ClientContextManager( "cloudformation", region_name=self.region ) as cloudformation: if self.pipeline_mode == constants.PIPELINE_MODE_SPILT: self.delete_pipelines( product_id, service_catalog, cloudformation ) else: self.info(f"Ensuring {self.name} is deleted") cloudformation.ensure_deleted(StackName=self.name) self.delete_from_service_catalog(product_id, service_catalog) self.info(f"Finished Deleting {self.name}") self.write_output({"found_product": found_product})
def quick_start(): click.echo("Quick Start running...") puppet_version = cli_command_helpers.get_puppet_version() with betterboto_client.ClientContextManager('sts') as sts: puppet_account_id = sts.get_caller_identity().get('Account') click.echo( "Going to use puppet_account_id: {}".format(puppet_account_id)) click.echo("Bootstrapping account as a spoke") with betterboto_client.ClientContextManager( 'cloudformation') as cloudformation: cli_command_helpers._do_bootstrap_spoke(puppet_account_id, cloudformation, puppet_version) click.echo("Setting the config") content = yaml.safe_dump( {"regions": ['eu-west-1', 'eu-west-2', 'eu-west-3']}) with betterboto_client.ClientContextManager('ssm') as ssm: ssm.put_parameter( Name=constants.CONFIG_PARAM_NAME, Type='String', Value=content, Overwrite=True, ) click.echo("Bootstrapping account as the master") org_iam_role_arn = cli_command_helpers._do_bootstrap_org_master( puppet_account_id, cloudformation, puppet_version) ssm.put_parameter( Name=constants.CONFIG_PARAM_NAME_ORG_IAM_ROLE_ARN, Type='String', Value=org_iam_role_arn, Overwrite=True, ) click.echo("Bootstrapping the account now!") cli_command_helpers._do_bootstrap(puppet_version) if os.path.exists('ServiceCatalogPuppet'): click.echo("Found ServiceCatalogPuppet so not cloning or seeding") else: click.echo("Cloning for you") command = "git clone " \ "--config 'credential.helper=!aws codecommit credential-helper $@' " \ "--config 'credential.UseHttpPath=true' " \ "https://git-codecommit.{}.amazonaws.com/v1/repos/ServiceCatalogPuppet".format( os.environ.get("AWS_DEFAULT_REGION") ) os.system(command) click.echo("Seeding") manifest = Template( asset_helpers.read_from_site_packages( os.path.sep.join(["manifests", "manifest-quickstart.yaml" ]))).render(ACCOUNT_ID=puppet_account_id) open(os.path.sep.join(["ServiceCatalogPuppet", "manifest.yaml"]), 'w').write(manifest) click.echo("Pushing manifest") os.system( "cd ServiceCatalogPuppet && git add manifest.yaml && git commit -am 'initial add' && git push" ) click.echo("All done!")
def run(self): with betterboto_client.ClientContextManager( 'servicecatalog', region_name=self.region) as service_catalog: self.info(f'Looking for product to delete: {self.name}') search_products_as_admin_response = service_catalog.search_products_as_admin_single_page( Filters={'FullTextSearch': [self.name]}) found_product = False for product_view_details in search_products_as_admin_response.get( 'ProductViewDetails'): product_view_summary = product_view_details.get( 'ProductViewSummary') if product_view_summary.get('Name') == self.name: found_product = True product_id = product_view_summary.get('ProductId') logger.info( f'Found product: {self.name}: {product_view_summary}') break if found_product: list_versions_response = service_catalog.list_provisioning_artifacts_single_page( ProductId=product_id) version_names = [ version['Name'] for version in list_versions_response.get( 'ProvisioningArtifactDetails', []) ] if len(version_names) > 0: self.info( f'Deleting Pipeline stacks for versions: {version_names} of {self.name}' ) with betterboto_client.ClientContextManager( 'cloudformation', region_name=self.region) as cloudformation: for version_name in version_names: self.info( f"Ensuring {self.uid}-{version_name} is deleted" ) cloudformation.ensure_deleted( StackName=f"{self.uid}-{version_name}") list_portfolios_response = service_catalog.list_portfolios_for_product_single_page( ProductId=product_id, ) portfolio_ids = [ portfolio_detail['Id'] for portfolio_detail in list_portfolios_response.get( 'PortfolioDetails', []) ] for portfolio_id in portfolio_ids: self.info( f'Disassociating {self.name} {product_id} from {portfolio_id}' ) service_catalog.disassociate_product_from_portfolio( ProductId=product_id, PortfolioId=portfolio_id) self.info( f'Deleting {self.name} {product_id} from Service Catalog') service_catalog.delete_product(Id=product_id, ) self.info(f'Finished Deleting {self.name}') self.write_output({})
def demo(p, type=click.Path(exists=True)): click.echo("Starting demo") click.echo("Setting up your config") config_yaml = 'config.yaml' if os.path.exists(os.path.sep.join([p, config_yaml])): click.echo('Using config.yaml') else: shutil.copy2(resolve_from_site_packages('example-config-small.yaml'), os.path.sep.join([p, config_yaml])) do_upload_config(os.path.sep.join([p, config_yaml])) click.echo("Finished setting up your config") do_bootstrap() commit_id_to_wait_for = add_or_update_file_in_branch_for_repo( 'master', 'portfolios/demo.yaml', read_from_site_packages('portfolios/example-simple.yaml'), 'ServiceCatalogFactory') click.echo('Waiting for the pipeline to finish') wait_for_pipeline(commit_id_to_wait_for, 'servicecatalog-factory-pipeline') product_name = 'account-iam' with betterboto_client.ClientContextManager('codecommit') as codecommit: response = codecommit.list_repositories() repo_name = product_name if repo_name not in [ r.get('repositoryName') for r in response.get('repositories', []) ]: click.echo('Creating {} repository'.format(repo_name)) codecommit.create_repository(repositoryName=repo_name, ) commit_id_to_wait_for = add_or_update_file_in_branch_for_repo( 'v1', 'product.template.yaml', requests.get( 'https://raw.githubusercontent.com/eamonnfaherty/cloudformation-templates/master/iam_admin_role/product.template.yaml' ).text, repo_name) wait_for_pipeline( commit_id_to_wait_for, 'demo-central-it-team-portfolio-account-iam-v1-pipeline') product_created = False with betterboto_client.ClientContextManager( 'servicecatalog') as servicecatalog: response = servicecatalog.search_products_as_admin() for product_view_detail in response.get('ProductViewDetails', []): if product_view_detail.get('ProductViewSummary').get( 'Name') == product_name: product_created = True click.echo("Created AWS ServiceCatalog product: {}".format( product_view_detail.get('ProductViewSummary').get( 'ProductId'))) assert product_created, 'Product was not created!' click.echo("Finished demo")
def handle_action_execution_detail(puppet_account_id, action_execution_detail): action_type_id = action_execution_detail.get("input").get("actionTypeId") if ( action_type_id.get("category") == "Build" and action_type_id.get("owner") == "AWS" and action_type_id.get("provider") == "CodeBuild" ): external_execution_id = ( action_execution_detail.get("output") .get("executionResult") .get("externalExecutionId") ) with betterboto_client.ClientContextManager( "codebuild", region_name=config.get_home_region(puppet_account_id) ) as codebuild: builds = codebuild.batch_get_builds(ids=[external_execution_id]).get( "builds" ) build = builds[0] log_details = build.get("logs") with betterboto_client.ClientContextManager( "logs", region_name=config.get_home_region(puppet_account_id) ) as logs: with open( f"log-{action_execution_detail.get('input').get('configuration').get('ProjectName')}.log", "w", ) as f: params = { "logGroupName": log_details.get("groupName"), "logStreamName": log_details.get("streamName"), "startFromHead": True, } has_more_logs = True while has_more_logs: get_log_events_response = logs.get_log_events(**params) if (len(get_log_events_response.get("events"))) > 0: params["nextToken"] = get_log_events_response.get( "nextForwardToken" ) else: has_more_logs = False if params.get("nextToken"): del params["nextToken"] for e in get_log_events_response.get("events"): d = datetime.utcfromtimestamp( e.get("timestamp") / 1000 ).strftime("%Y-%m-%d %H:%M:%S") f.write(f"{d} : {e.get('message')}")
def run(self): template_contents = self.input().open("r").read() template = cfn_tools.load_yaml(template_contents) friendly_uid = template.get("Description").split("\n")[0] self.info(f"creating the stack: {friendly_uid}") tags = [] for tag in self.tags: tags.append( {"Key": tag.get("Key"), "Value": tag.get("Value"),} ) with betterboto_client.ClientContextManager("cloudformation") as cloudformation: if self.provisioner.get("Type") == "CloudFormation": response = cloudformation.create_or_update( StackName=friendly_uid, TemplateBody=template_contents, Tags=tags, ) elif self.provisioner.get("Type") == "Terraform": response = cloudformation.create_or_update( StackName=friendly_uid, TemplateBody=template_contents, Parameters=[ { "ParameterKey": "Version", "ParameterValue": self.factory_version, "UsePreviousValue": False, }, ], Tags=tags, ) with self.output().open("w") as f: f.write(json.dumps(response, indent=4, default=str,)) self.info(f"Finished")
def run(self): template_contents = self.input().open("r").read() template = cfn_tools.load_yaml(template_contents) friendly_uid = template.get("Description").split("\n")[0] self.info(f"creating the stack: {friendly_uid}") tags = [] for tag in self.product.get("Tags"): tags.append({ "Key": tag.get("Key"), "Value": tag.get("Value"), }) provisioner = self.product.get("Provisioner", {}).get("Type", constants.PROVISIONERS_DEFAULT) with betterboto_client.ClientContextManager( "cloudformation") as cloudformation: if provisioner == constants.PROVISIONERS_CLOUDFORMATION: response = cloudformation.create_or_update( StackName=friendly_uid, TemplateBody=template_contents, Tags=tags, ) else: raise Exception( f"Unknown/unsupported provisioner: {provisioner}") self.info(f"Finished") self.write_output(response)
def wait_for_pipeline(commit_id_to_wait_for, pipeline_name): pipeline_execution = None with betterboto_client.ClientContextManager( 'codepipeline') as codepipeline: while pipeline_execution is None: click.echo('Looking for pipeline execution') time.sleep(1) response = codepipeline.list_pipeline_executions( pipelineName=pipeline_name) for pipeline_execution_summary in response.get( 'pipelineExecutionSummaries', []): for source_revision in pipeline_execution_summary.get( 'sourceRevisions', []): if source_revision.get( 'revisionId') == commit_id_to_wait_for: pipeline_execution = pipeline_execution_summary click.echo("Found pipeline execution") pipeline_execution['status'] = 'InProgress' while pipeline_execution.get('status') == 'InProgress': click.echo("Waiting for execution to complete") time.sleep(1) response = codepipeline.get_pipeline_execution( pipelineName=pipeline_name, pipelineExecutionId=pipeline_execution.get('pipelineExecutionId')) pipeline_execution = response.get('pipelineExecution') if pipeline_execution.get('status') == 'Succeeded': click.echo("Pipeline finished running") else: raise Exception( 'Pipeline failed to run: {}'.format(pipeline_execution))
def get_portfolios_by_file_name(portfolio_file_name): with betterboto_client.ClientContextManager('codecommit') as codecommit: content = codecommit.get_file( repositoryName=constants.SERVICE_CATALOG_FACTORY_REPO_NAME, filePath=f"portfolios/{portfolio_file_name}", ).get('fileContent') return yaml.safe_load(content)
def get_build_info(build_id_list: list): """ Returns the CodeBuild build information for the supplied CodeBuild build IDds. Parameters: build_id_list (list): List of CodeBuild build Ids Returns: build_info (list): List of dict objects with the information for each of the supplied build Ids """ build_info = [] logger.info(f"Getting information for {len(build_id_list)} builds") while len(build_id_list) > 0: logger.info(f"list length {len(build_id_list)}") inner_build_list = build_id_list[:50] with betterboto_client.ClientContextManager("codebuild") as codebuild: response = codebuild.batch_get_builds(ids=inner_build_list) for build in response["builds"]: duration = build["endTime"] - build["startTime"] inner_response_dict = { "id": build["id"], "start": build["startTime"], "duration_in_seconds": str(round(duration.total_seconds())), "status": build["buildStatus"], } build_info.append(inner_response_dict) del build_id_list[:50] return build_info
def add_secret(secret_name, oauth_token, secret_token): with betterboto_client.ClientContextManager('secretsmanager') as secretsmanager: try: secretsmanager.create_secret( Name=secret_name, SecretString=json.dumps( { 'OAuthToken': oauth_token, 'SecretToken': secret_token or oauth_token, } ), ) except secretsmanager.exceptions.ResourceExistsException: secretsmanager.put_secret_value( SecretId=secret_name, SecretString=json.dumps( { 'OAuthToken': oauth_token, 'SecretToken': secret_token or oauth_token, } ), VersionStages=[ 'AWSCURRENT', ] ) click.echo("Uploaded secret")
def create_share_template(deployment_map, import_map, puppet_account_id): logger.info("deployment_map: {}".format(deployment_map)) ALL_REGIONS = get_regions() for region in ALL_REGIONS: logger.info("starting to build shares for region: {}".format(region)) with betterboto_client.ClientContextManager('servicecatalog', region_name=region) as servicecatalog: portfolio_ids = {} response = servicecatalog.list_portfolios_single_page() for portfolio_detail in response.get('PortfolioDetails'): portfolio_ids[portfolio_detail.get('DisplayName')] = portfolio_detail.get('Id') logger.info("Portfolios in use in region: {}".format(portfolio_ids)) portfolio_use_by_account = {} for account_id, launch_details in deployment_map.items(): if portfolio_use_by_account.get(account_id) is None: portfolio_use_by_account[account_id] = [] for launch_id, launch in launch_details.get('launches').items(): p = portfolio_ids[launch.get('portfolio')] if p not in portfolio_use_by_account[account_id]: portfolio_use_by_account[account_id].append(p) for account_id, import_details in import_map.items(): if portfolio_use_by_account.get(account_id) is None: portfolio_use_by_account[account_id] = [] for spoke_local_portfolio_id, spoke_local_portfolio in import_details.get('spoke-local-portfolios').items(): p = portfolio_ids[spoke_local_portfolio.get('portfolio')] if p not in portfolio_use_by_account[account_id]: portfolio_use_by_account[account_id].append(p) host_account_id = response.get('PortfolioDetails')[0].get('ARN').split(":")[4] sharing_policies = generate_bucket_policies_for_shares(deployment_map, puppet_account_id) write_share_template(portfolio_use_by_account, region, host_account_id, sharing_policies)
def run(self): product = json.loads(self.input().open('r').read()) product_id = product.get('ProductId') version_name = self.version.get('Name') version_active = self.version.get('Active', True) with betterboto_client.ClientContextManager( 'servicecatalog', region_name=self.region) as service_catalog: response = service_catalog.list_provisioning_artifacts( ProductId=product_id) logger.info("Checking through: {}".format(response)) for provisioning_artifact_detail in response.get( 'ProvisioningArtifactDetails', []): if provisioning_artifact_detail.get('Name') == version_name: logger.info( f"Found matching: {version_name}: {provisioning_artifact_detail}" ) if provisioning_artifact_detail.get( 'Active') != version_active: logger.info( f"Active status needs to change for: {product.get('Name')} {version_name}" ) service_catalog.update_provisioning_artifact( ProductId=product_id, ProvisioningArtifactId=provisioning_artifact_detail .get('Id'), Active=version_active, ) with self.output().open('w') as f: f.write("{}")
def delete_stack_from_a_regions(stack_name, region): click.echo("Deleting stack: {} from region: {}".format(stack_name, region)) with betterboto_client.ClientContextManager('cloudformation', region_name=region) as cloudformation: cloudformation.delete_stack(StackName=stack_name) waiter = cloudformation.get_waiter('stack_delete_complete') waiter.wait(StackName=stack_name) click.echo("Finished")
def run(self): logger_prefix = f"{self.region}-{self.portfolio_group_name}-{self.display_name}" with betterboto_client.ClientContextManager( 'servicecatalog', region_name=self.region) as service_catalog: generated_portfolio_name = f"{self.portfolio_group_name}-{self.display_name}" tags = [] for t in self.tags: tags.append({ "Key": t.get('Key'), "Value": t.get('Value'), }) tags.append({ "Key": "ServiceCatalogFactory:Actor", "Value": "Portfolio" }) portfolio_detail = aws.get_or_create_portfolio( self.description, self.provider_name, generated_portfolio_name, tags, service_catalog) if portfolio_detail is None: raise Exception("portfolio_detail was not found or created") with self.output().open('w') as f: logger.info(f"{logger_prefix}: about to write! {portfolio_detail}") f.write(json.dumps( portfolio_detail, indent=4, default=str, ))
def release_spoke(puppet_account_id): with betterboto_client.ClientContextManager( "cloudformation", region_name=config.get_home_region( puppet_account_id)) as cloudformation: cloudformation.ensure_deleted( StackName=f"{constants.BOOTSTRAP_STACK_NAME}-spoke")
def run(self): logger_prefix = f"{self.product.get('Name')}-{self.version.get('Name')}" template_contents = self.input().open('r').read() template = cfn_tools.load_yaml(template_contents) friendly_uid = template.get('Description').split('\n')[0] logger.info(f"{logger_prefix} creating the stack: {friendly_uid}") with betterboto_client.ClientContextManager( 'cloudformation') as cloudformation: if self.provisioner.get('Type') == 'CloudFormation': response = cloudformation.create_or_update( StackName=friendly_uid, TemplateBody=template_contents, ) elif self.provisioner.get('Type') == 'Terraform': response = cloudformation.create_or_update( StackName=friendly_uid, TemplateBody=template_contents, Parameters=[ { 'ParameterKey': 'Version', 'ParameterValue': self.factory_version, 'UsePreviousValue': False, }, ], ) with self.output().open('w') as f: f.write(json.dumps( response, indent=4, default=str, )) logger.info(f"{logger_prefix} - Finished")
def assemble_manifest_from_ssm(target_directory): with betterboto_client.ClientContextManager("ssm") as ssm: paginator = ssm.get_paginator("get_parameters_by_path") manifest = { "schema": "puppet-2019-04-01", constants.LAUNCHES: dict(), constants.STACKS: dict(), constants.SPOKE_LOCAL_PORTFOLIOS: dict(), constants.ASSERTIONS: {}, constants.CODE_BUILD_RUNS: {}, constants.LAMBDA_INVOCATIONS: {}, constants.APPS: {}, constants.WORKSPACES: {}, constants.CFCT: {}, constants.SERVICE_CONTROL_POLICIES: {}, constants.SIMULATE_POLICIES: {}, constants.TAG_POLICIES: {}, } for page in paginator.paginate( Path=constants.SERVICE_CATALOG_PUPPET_MANIFEST_SSM_PREFIX, Recursive=True, ): for parameter in page.get("Parameters", []): parts = parameter.get("Name").split("/") action_type = parts[3] action_name = parts[4] manifest[action_type][action_name] = yaml_utils.load( parameter.get("Value") ) if not os.path.exists(target_directory): os.makedirs(target_directory) open(f"{target_directory}{os.path.sep}ssm_manifest.yaml", "w").write( yaml_utils.dump(manifest) )
def get_manifest(): with betterboto_client.ClientContextManager('codecommit') as codecommit: content = codecommit.get_file( repositoryName=constants.SERVICE_CATALOG_PUPPET_REPO_NAME, filePath="manifest.yaml", ).get('fileContent') return yaml.safe_load(content)
def provision_stack(stack_name_suffix: str, template: str) -> None: with betterboto_client.ClientContextManager( "cloudformation", ) as cloudformation: cloudformation.create_or_update( StackName=f"AWSOrganized-{stack_name_suffix}", TemplateBody=template, Capabilities=["CAPABILITY_NAMED_IAM"], )
def bootstrap_org_master(puppet_account_id): with betterboto_client.ClientContextManager( 'cloudformation', ) as cloudformation: org_iam_role_arn = cli_command_helpers._do_bootstrap_org_master( puppet_account_id, cloudformation, cli_command_helpers.get_puppet_version()) click.echo("Bootstrapped org master, org-iam-role-arn: {}".format( org_iam_role_arn))
def get_config(default_region=None): logger.info("getting config, default_region: {}".format(default_region)) with betterboto_client.ClientContextManager( 'ssm', region_name=default_region if default_region else get_home_region()) as ssm: response = ssm.get_parameter(Name=constants.CONFIG_PARAM_NAME) return yaml.safe_load(response.get('Parameter').get('Value'))
def set_named_config_value(name, value): with betterboto_client.ClientContextManager( "ssm", region_name=constants.HOME_REGION ) as ssm: ssm.put_parameter( Name=name, Type="String", Value=value, Overwrite=True, ) click.echo("Uploaded named config")
def bootstrap_spoke(puppet_account_id, permission_boundary): with betterboto_client.ClientContextManager('cloudformation') as cloudformation: _do_bootstrap_spoke( puppet_account_id, cloudformation, config.get_puppet_version(), permission_boundary )
def get_org_iam_role_arn(): with betterboto_client.ClientContextManager('ssm', region_name=get_home_region()) as ssm: try: response = ssm.get_parameter(Name=constants.CONFIG_PARAM_NAME_ORG_IAM_ROLE_ARN) return yaml.safe_load(response.get('Parameter').get('Value')) except ssm.exceptions.ParameterNotFound as e: logger.info("No parameter set for: {}".format(constants.CONFIG_PARAM_NAME_ORG_IAM_ROLE_ARN)) return None
def run(self): logger_prefix = f"{self.region}-{self.name}" with betterboto_client.ClientContextManager( 'servicecatalog', region_name=self.region) as service_catalog: tags = [] for t in self.tags: tags.append({ "Key": t.get('Key'), "Value": t.get('Value'), }) tags.append({ "Key": "ServiceCatalogFactory:Actor", "Value": "Product" }) s3_bucket_name = self.load_from_input('s3_bucket_url').get( 's3_bucket_url') args = { 'ProductType': 'CLOUD_FORMATION_TEMPLATE', 'ProvisioningArtifactParameters': { 'Name': "-", 'Type': 'CLOUD_FORMATION_TEMPLATE', 'Description': 'Placeholder version, do not provision', "Info": { "LoadTemplateFromURL": "https://s3.amazonaws.com/{}/{}".format( s3_bucket_name, "empty.template.yaml") } }, "Name": self.name, "Owner": self.owner, "Description": self.description, "Distributor": self.distributor, "SupportDescription": self.support_description, "SupportEmail": self.support_email, "SupportUrl": self.support_url, "Tags": tags } product_view_summary = aws.get_or_create_product( self.name, args, service_catalog) if product_view_summary is None: raise Exception( f"{logger_prefix}: did not find or create a product") product_view_summary['uid'] = self.uid with self.output().open('w') as f: logger.info( f"{logger_prefix}: about to write! {product_view_summary}") f.write( json.dumps( product_view_summary, indent=4, default=str, ))
def upload_config(config): with betterboto_client.ClientContextManager('ssm') as ssm: ssm.put_parameter( Name=constants.CONFIG_PARAM_NAME, Type='String', Value=yaml.safe_dump(config), Overwrite=True, ) click.echo("Uploaded config")
def exists(self): with betterboto_client.ClientContextManager('ssm') as ssm: try: ssm.get_parameter(Name=self.param_name, ).get('Parameter') return True except ssm.exceptions.ParameterNotFound as e: if self.error_when_not_found: raise e return False
def set_org_iam_role_arn(org_iam_role_arn): with betterboto_client.ClientContextManager('ssm') as ssm: ssm.put_parameter( Name=constants.CONFIG_PARAM_NAME_ORG_IAM_ROLE_ARN, Type='String', Value=org_iam_role_arn, Overwrite=True, ) click.echo("Uploaded config")