def get_subnet_ids(vpc, azs, params, name_search_string=""): subnet_ids = [] session, err = get_session(params) if not err: try: ec2 = session.resource('ec2') for az in azs: for subnet in vpc.subnets.filter( Filters=[{ "Name": "availabilityZone", "Values": [az] }, { 'Name': 'tag:Name', 'Values': ['*%s*' % name_search_string] }]): subnet_ids.append(subnet.id) except botocore.exceptions.ClientError as e: err = e else: err = "error determining subnet ids: %s" % err return subnet_ids, err
def initialize(self, params): err = "" # get a boto3 session self.session, err = get_session(params) if not err and self.session: vault_exists_bool = self.vault_exists() if vault_exists_bool: s3 = self.session.resource('s3') # pull file down to the local dir err = s3.meta.client.download_file(self.vault_bucket, self.vault_s3_path, self.vault_path) # load the file contents FileVault.initialize(self, params) else: err = "vault at %s does not exist" % self.vault_s3_path
def changes(self, params, context): self.params = params # initialize a session with boto3 self.session, err = get_session(self.params) self.name = get_stack_name(self.params) # apply intrinsics to the stack template rendered_stack_template = apply_intrinsics(self.serialize(), self.params) stack_exits_bool = self.exists() # determine if we are building or updating this stack action = UPDATING if stack_exits_bool else BUILDING stack_state = self.get_stack_state() # print stack template to a string stack_template_str = json.dumps(rendered_stack_template) service_name = self.params.get('service-name') service_alias = self.params.get('service-alias') if action == UPDATING: analyze_changes = input( "(BETA!) Analyze changes associated with this stack update? (y/n)> " ) if analyze_changes and analyze_changes == 'y': # get stack params stack_params = self.cf_param_map.get_params_array( self.params, self.session, self.name, True) # Get the optional "staging" location where the stack template can be staged. # The location is only used if the template string exceeds Amazon API's character limit. template_staging_path = self.params.get( 'template-staging-s3-path', "") change_arn, change_error = self.analyze_changes( template_string=stack_template_str, stack_params=stack_params, template_staging_path=template_staging_path) if not change_error: print( "Changes associated with this update can be viewed via the cloudformation console" ) print( "See the 'proposed-changes' change set via the 'Change Sets' tab on the %s stack" % self.name) else: print("Change set creation failed with error: %s" % change_error)
def cost(self, params, context): self.params = params # initialize a session with boto3 self.session, err = get_session(params) self.name = get_stack_name(self.params) # apply intrinsics to the stack template rendered_stack_template = apply_intrinsics(self.serialize(), self.params) stack_exits_bool = self.exists() # determine if we are building or updating this stack action = UPDATING if stack_exits_bool else BUILDING stack_state = self.get_stack_state() # print stack template to a string stack_template_str = json.dumps(rendered_stack_template) service_name = self.params.get('service-name') service_alias = self.params.get('service-alias') estimate_cost = input( "Estimate cost associate with stack resources? (y/n)> ") if estimate_cost and estimate_cost == 'y': # get stack params stack_params = self.cf_param_map.get_params_array( self.params, self.session, self.name, True) # Get the optional "staging" location where the stack template can be staged. # The location is only used if the template string exceeds Amazon API's character limit. template_staging_path = self.params.get('template-staging-s3-path', "") cost_response, cost_error = self.cost_stack( template_string=stack_template_str, stack_params=stack_params, template_staging_path=template_staging_path) if not cost_error: print( "Cost of the resources for this service can be viewed here: %s" % (cost_response)) else: print("Costing failed: %s" % cost_error)
def dryrun(self, params, deploy_mode_bool=False, context=""): self.params = params # initialize a session with boto3 self.session, err = get_session(params) self.name = get_stack_name(self.params) # deploy any boot files specified by the service self.boot_files.deploy(self.params, context, dry_run_bool=True) # apply intrinsics to the stack template rendered_stack_template = apply_intrinsics(self.serialize(), self.params) stack_exits_bool = self.exists() # determine if we are building or updating this stack action = UPDATING if stack_exits_bool else BUILDING stack_state = self.get_stack_state() service_name = self.params.get('service-name') service_alias = self.params.get('service-alias') servicefile_path = self.params.get('servicefile-path') print("%s (dry-run) the %s service aliased as '%s'" % (action, service_name, service_alias)) print("Stack state is currently: %s." % stack_state) print("Service stack will be named: %s" % self.name) # show the rendered templates self.show_rendered_templates(rendered_stack_template, deploy_mode_bool, service_alias) stack_params = self.cf_param_map.get_params_array( self.params, self.session, self.name) if stack_params: print("Param mapping:\n%s" % stack_params) print("Sanity check the params above.")
def get_vpcs(params, name_search_string=""): vpcs = [] session, err = get_session(params) if not err: try: ec2 = session.resource('ec2') vpcs = list( ec2.vpcs.filter( Filters=[{ 'Name': 'tag:Name', 'Values': ['*%s*' % name_search_string] }])) except botocore.exceptions.ClientError as e: err = e return vpcs, err
def ami_exists(self, params, ami_name): ami_exists = False session, err = get_session(params) if not err: client = session.client('ec2') response = client.describe_images(Filters=[{ 'Name': 'name', 'Values': [ami_name] }]) else: return err if "Images" in response and len(response["Images"]) == 1: ami_exists = True return ami_exists
def _deploy_files(self, context, dry_run_bool): servicefile_path = self.params.get("servicefile-path") dump_path = get_dump_path(self.params.get("service-alias")) session, err = get_session(self.params) for this_file in self.files: if 'file-params' in this_file: file_params = Params(this_file['file-params']) # combine file params with the other params self.params.add(file_params) # render templates in the serialized file descriptor rendered_boot_file = apply_intrinsics(this_file, self.params) # if necessary, localize file localized_file = localize_file(rendered_boot_file['src'], servicefile_path) if os.path.exists(localized_file): # replace any service parmeters variables in the file body and # return the name+path of the "rendered" file rendered_file = apply_templates_in_file( localized_file, self.params, dump_path) # if destination is s3 bucket and this is not a dry run if (self._is_s3_destination(rendered_boot_file['dest']) and rendered_file): # copy rendered file to s3 destination self.cp_file_to_s3(session, rendered_file, rendered_boot_file['dest'], dry_run_bool) # if destination is another local file (mostly used for testing) elif not dry_run_bool: # make sure destination directory exists if not os.path.exists( os.path.dirname(rendered_boot_file['dest'])): os.makedirs(os.path.dirname( rendered_boot_file['dest'])) # copy rendered file to the destination shutil.copy(rendered_file, rendered_boot_file['dest']) else: error_msg = ( "%s file deploy was not performed." % localized_file + " Source file is missing") raise FileError(error_msg) if self.files and dry_run_bool: print("Rendered boot files can be viewed under: %s" % (dump_path))
def build(self, params, deploy_mode_bool=False, context=""): self.params = params pipeline_run = params.get('pipeline-run', False) # initialize a session with boto3 self.session, err = get_session(params) self.name = get_stack_name(self.params) # deploy any boot files specified by the service self.boot_files.deploy(self.params, context, dry_run_bool=False) # apply intrinsics to the stack template rendered_stack_template = apply_intrinsics(self.serialize(), self.params) stack_exits_bool = self.exists() # make sure stack is in an actionable state before proceeding stack_actionable, err = self.is_actionable() # if the stack does not yet exist, or if the stack exists and is in # an actionable state ... if (stack_exits_bool == False or stack_actionable): service_name = self.params.get('service-name') service_alias = self.params.get('service-alias') # determine if we are building or updating this stack action = UPDATING if stack_exits_bool else BUILDING # show build plan via stdout print("%s the %s service aliased as '%s'" % (action, service_name, service_alias)) print("Service stack will be named: %s" % (self.name)) if pipeline_run is True: # give user chance to bail print("Hit <enter> to continue...") # get stack parameters stack_params = self.cf_param_map.get_params_array( self.params, self.session, self.name) # Get the optional "staging" location where the stack template can be staged. # The location is only used if the template string exceeds Amazon API's character limit. template_staging_path = self.params.get('template-staging-s3-path', "") # dump stack template to a string stack_template_str = json.dumps(rendered_stack_template) if action == BUILDING: response, err = self.create_stack( template_string=stack_template_str, stack_params=stack_params, template_staging_path=template_staging_path) if not err: print( 'Stack creation in progress - use AWS console to watch construction and/or see errors' ) else: response, err = self.update_stack( template_string=stack_template_str, stack_params=stack_params, template_staging_path=template_staging_path) if not err: print( 'Stack update in progress - use AWS console to watch updates and/or see errors' ) # if this build is happening in the context of a deploy if deploy_mode_bool: # wait for stack update to complete self.wait() # return any errors return err