def get_version_data(self): """Gets app_versions data by pages. Pages that were already accessed would be stored in history Then modifies app_versions: add SinceCreated field and format DateCreated field for each version in app_versions. Paginates, so appends PAGE_LENGTH versions with each call :returns data object with two keys: environment and app_versions note: environment data would be None if no environment is specified """ if self.list_len_left <= 0: return self.get_table_data() if self.next_token: response = elasticbeanstalk.get_application_versions(self.app_name, None, self.PAGE_LENGTH, self.next_token) else: response = elasticbeanstalk.get_application_versions(self.app_name, None, self.PAGE_LENGTH) new_page_versions = response['ApplicationVersions'] self.next_token = None if u'NextToken' in response: self.next_token = response['NextToken'] self.prep_version_data(new_page_versions) self.history.append(self.app_versions) self.curr_page += 1 return self.get_table_data()
def get_version_data(self): """ Gets app_versions data by pages. Pages that were already accessed would be stored in history Then modifies app_versions: add SinceCreated field and format DateCreated field for each version in app_versions. Paginates, so appends PAGE_LENGTH versions with each call :returns data object with two keys: environment and app_versions note: environment data would be None if no environment is specified """ if self.list_len_left <= 0: return self.get_table_data() if self.next_token: response = elasticbeanstalk.get_application_versions( self.app_name, None, self.PAGE_LENGTH, self.next_token) else: response = elasticbeanstalk.get_application_versions( self.app_name, None, self.PAGE_LENGTH) new_page_versions = response['ApplicationVersions'] self.next_token = None if u'NextToken' in response: self.next_token = response['NextToken'] self.prep_version_data(new_page_versions) self.history.append(self.app_versions) self.curr_page += 1 return self.get_table_data()
def delete_app_version_label(app_name, version_label): if version_label: # check if version_label exists under app_name app_versions = elasticbeanstalk.get_application_versions(app_name)['ApplicationVersions'] # if the given version label does not exist at all! if not any(version_label == app_version['VersionLabel'] for app_version in app_versions): raise ValidationError(strings['appversion.delete.notfound'].format(app_name, version_label)) envs = elasticbeanstalk.get_app_environments(app_name) versions_in_use = [(e.version_label, e.name) for e in envs] # find all the environments that are using the app version used_envs = [version[1] for version in versions_in_use if version[0] == version_label] if used_envs: raise ValidationError(strings['appversion.delete.deployed'].format(version_label, ','.join(used_envs))) try: io.validate_action(prompts['appversion.delete.validate'].format(version_label), "y") elasticbeanstalk.delete_application_version(app_name, version_label) io.echo('Application Version deleted successfully.') delete_successful = True except ValidationError: io.echo('Application Version will not be deleted.') delete_successful = False return delete_successful else: raise NotFoundError(strings['appversion.delete.none'])
def stream_build_configuration_app_version_creation(app_name, app_version_label): # Get the CloudWatch logs link successfully_generated = wait_for_app_version_attribute( app_name, [app_version_label], 'BuildArn', timeout=1) app_version_response = elasticbeanstalk.get_application_versions( app_name, version_labels=[app_version_label])['ApplicationVersions'] build_response = codebuild.batch_get_builds([app_version_response[0]['BuildArn']]) \ if successfully_generated else None if build_response is not None and 'logs' in build_response['builds'][0]: log_link_text = strings['codebuild.buildlogs'].replace( '{logs_link}', build_response['builds'][0]['logs']['deepLink']) io.echo(log_link_text) else: io.log_warning("Could not retrieve CloudWatch link for CodeBuild logs") # Wait for the success events try: from ebcli.operations.commonops import wait_for_success_events wait_for_success_events(None, timeout_in_minutes=5, can_abort=False, version_label=app_version_label) except ServiceError as ex: LOG.debug( "Caught service error while creating application version '{0}' " "deleting the created applicaiton version as it is useless now.") elasticbeanstalk.delete_application_version(app_name, app_version_label) raise ex
def wait_for_app_version_attribute(app_name, version_labels, timeout=5): io.echo('--- Waiting for Application Versions to populate attributes ---') versions_to_check = list(version_labels) found = dict.fromkeys(version_labels) failed = dict.fromkeys(version_labels) start_time = datetime.utcnow() timediff = timedelta(minutes=timeout) while versions_to_check: if _timeout_reached(start_time, timediff): io.log_error(strings['appversion.attribute.failed'].replace( '{app_version}', ', '.join(version_labels))) return False io.LOG.debug('Retrieving app versions.') app_versions = elasticbeanstalk.get_application_versions( app_name, versions_to_check)['ApplicationVersions'] for version in app_versions: if version.get('BuildArn'): found[version['VersionLabel']] = True io.echo(strings['appversion.attribute.success'].format( app_version=version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) elif version.get('Status') == 'FAILED': failed[version['VersionLabel']] = True io.log_error(strings['appversion.attribute.failed'].format( app_version=version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) if all(found.values()): return True _sleep() return not any(failed.values())
def interactive_list_version(self): """Interactive mode which allows user to see previous versions and allow a choice to: - deploy a different version. - delete a certain version Run when the user supplies no argument to the --delete flag. """ app_versions = elasticbeanstalk.get_application_versions(self.app_name)['ApplicationVersions'] appversionops.display_versions(self.app_name, self.env_name, app_versions)
def do_command(self): app_name = self.get_app_name() num_to_leave = self.app.pargs.num_to_leave older_than = self.app.pargs.older_than force = self.app.pargs.force envs = elasticbeanstalk.get_app_environments(app_name) versions_in_use = [e.version_label for e in envs] app_versions = elasticbeanstalk.get_application_versions( app_name)['ApplicationVersions'] app_versions.sort(key=itemgetter('DateUpdated'), reverse=True) # Filter out versions currently being used app_versions = [ v for v in app_versions if v['VersionLabel'] not in versions_in_use ] total_num_unused_versions = len(app_versions) if total_num_unused_versions < num_to_leave: io.echo( 'Not enough unused application version to leave behind {0}; No application versions to delete.' .format(num_to_leave)) return # Filter out versions newer than filter date app_versions = [ v for v in app_versions if utils.get_delta_from_now_and_datetime( v['DateUpdated']).days > older_than ] # dont include most recent app_versions = app_versions[num_to_leave:] if app_versions: if not force: response = io.get_boolean_response( '{} application versions will be deleted. ' 'Continue?'.format(len(app_versions))) if not response: return else: io.echo('No application versions to delete.') return for version in app_versions: label = version['VersionLabel'] try: elasticbeanstalk.delete_application_version(app_name, label) except ServiceError as e: io.log_warning('Error deleting version {0}. Error: {1}'.format( label, e.message))
def stream_build_configuration_app_version_creation(app_name, app_version_label, build_spec): # Get the CloudWatch logs link successfully_generated = wait_for_app_version_attribute( app_name, [app_version_label], timeout=1 ) app_version_response = elasticbeanstalk.get_application_versions( app_name, version_labels=[app_version_label] )['ApplicationVersions'] build_response = codebuild.batch_get_builds([app_version_response[0]['BuildArn']]) \ if successfully_generated else None codebuild_timeout = build_spec.timeout or 60 if build_response is not None and 'logs' in build_response['builds'][0]: log_link_text = strings['codebuild.buildlogs'].replace( '{logs_link}', build_response['builds'][0]['logs']['deepLink'] ) io.echo(log_link_text) io.echo( "NOTE: The CodeBuild timeout is set to {0} minutes, so this " "operation may take upto '{0}' minutes to complete.".format(codebuild_timeout) ) else: io.log_warning("Could not retrieve CloudWatch link for CodeBuild logs") try: # Need to lazy-import `ebcli.lib.commonops` because `pytest` is unable to load it # at module load-time using Python 2.7 and Python 3.4 from ebcli.operations import commonops timeout_error_message = ' '.join([ 'The CodeBuild build timed out after {} minute(s).'.format(codebuild_timeout), "To increase the time limit, use the 'Timeout' option in the 'buildspec.yml' file." ]) commonops.wait_for_success_events( app_name=app_name, can_abort=False, request_id=None, timeout_error_message=timeout_error_message, timeout_in_minutes=codebuild_timeout, version_label=app_version_label ) except ServiceError as exception: LOG.debug("Caught service error while creating application version '{0}' " "deleting the created application version as it is useless now.".format(app_version_label)) elasticbeanstalk.delete_application_version(app_name, app_version_label) raise exception
def wait_for_app_version_attribute(app_name, version_labels, attribute, timeout=5): versions_to_check = list(version_labels) found = {} failed = {} io.echo('--- Waiting for Application Versions to populate attributes ---') for version in version_labels: found[version] = False failed[version] = False start_time = datetime.utcnow() while not all([(found[version] or failed[version]) for version in versions_to_check]): if datetime.utcnow() - start_time >= timedelta(minutes=timeout): io.log_error(strings['appversion.attribute.failed'].replace( '{app_version}', version_labels)) return False io.LOG.debug('Retrieving app versions.') app_versions = elasticbeanstalk.get_application_versions( app_name, versions_to_check)['ApplicationVersions'] for version in app_versions: if attribute in version: if version[attribute] is not None: found[version['VersionLabel']] = True io.echo(strings['appversion.attribute.success'].replace( '{app_version}', version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) elif 'Status' in version and (version['Status'] == 'FAILED' or version['Status'] == 'FAILED'): failed[version['VersionLabel']] = True io.log_error(strings['appversion.attribute.failed'].replace( '{app_version}', version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) if all(found.values()): return True time.sleep(4) if any(failed.values()): return False return True
def cleanup_application_versions(app_name): io.echo('Removing application versions from s3.') versions = elasticbeanstalk.get_application_versions( app_name)['ApplicationVersions'] buckets = defaultdict(list) for version in versions: bundle = version.get('SourceBundle', {}) bucket = bundle.get('S3Bucket') key = bundle.get('S3Key') if bucket and key: buckets[bucket].append(key) for bucket, keys in six.iteritems(buckets): try: s3.delete_objects(bucket, keys) except NotAuthorizedError: io.log_warning( 'Error deleting application versions from bucket "{0}"'.format( bucket))
def download_source_bundle(app_name, env_name): env = elasticbeanstalk.get_environment(app_name=app_name, env_name=env_name) if env.version_label and env.version_label != 'Sample Application': app_version = elasticbeanstalk.get_application_versions( app_name, version_labels=[env.version_label])['ApplicationVersions'][0] source_bundle = app_version['SourceBundle'] bucket_name = source_bundle['S3Bucket'] key_name = source_bundle['S3Key'] io.echo('Downloading application version...') data = s3.get_object(bucket_name, key_name) filename = get_filename(key_name) else: # sample app template = cloudformation.get_template('awseb-' + env.id + '-stack') try: url = template['TemplateBody']['Parameters']['AppSource'][ 'Default'] except KeyError: raise NotFoundError('Can not find app source for environment') utils.get_data_from_url(url) io.echo('Downloading application version...') data = utils.get_data_from_url(url, timeout=30) filename = 'sample.zip' fileoperations.make_eb_dir('downloads/') location = fileoperations.get_eb_file_full_location('downloads/' + filename) fileoperations.write_to_data_file(location, data) io.echo('Application version downloaded to:', location) cwd = os.getcwd() try: fileoperations._traverse_to_project_root() if heuristics.directory_is_empty(): # If we dont have any project code, unzip as current project io.echo('Unzipping application version as project files.') fileoperations.unzip_folder(location, os.getcwd()) io.echo('Done.') finally: os.chdir(cwd)
def wait_for_processed_app_versions(app_name, version_labels, timeout=5): versions_to_check = list(version_labels) processed = {} failed = {} io.echo('--- Waiting for Application Versions to be pre-processed ---') for version in version_labels: processed[version] = False failed[version] = False start_time = datetime.utcnow() timediff = timedelta(seconds=timeout * 60) while not all([(processed[version] or failed[version]) for version in versions_to_check]): if _timeout_reached(start_time, timediff): io.log_error(strings['appversion.processtimeout']) return False io.LOG.debug('Retrieving app versions.') app_versions = elasticbeanstalk.get_application_versions( app_name, versions_to_check )["ApplicationVersions"] for v in app_versions: if v['Status'] == 'PROCESSED': processed[v['VersionLabel']] = True io.echo('Finished processing application version {}' .format(v['VersionLabel'])) versions_to_check.remove(v['VersionLabel']) elif v['Status'] == 'FAILED': failed[v['VersionLabel']] = True io.log_error(strings['appversion.processfailed'].replace('{app_version}', v['VersionLabel'])) versions_to_check.remove(v['VersionLabel']) if all(processed.values()): return True _sleep(4) if any(failed.values()): io.log_error(strings['appversion.cannotdeploy']) return False return True
def get_quick_link(app_name, env_name): env = elasticbeanstalk.get_environment(app_name=app_name, env_name=env_name) settings = elasticbeanstalk.describe_configuration_settings( app_name, env_name) option_settings = settings['OptionSettings'] environment_type = elasticbeanstalk.get_option_setting( option_settings, 'aws:elasticbeanstalk:environment', 'EnvironmentType') instance_type = elasticbeanstalk.get_option_setting( option_settings, 'aws:autoscaling:launchconfiguration', 'InstanceType') link = 'https://console.aws.amazon.com/elasticbeanstalk/home?' # add region region = aws.get_region_name() link += 'region=' + urllib.parse.quote(region) # add quicklaunch flag link += '#/newApplication' # add application name link += '?applicationName=' + urllib.parse.quote(app_name) # add solution stack link += '&solutionStackName=' + urllib.parse.quote( env.platform.platform_shorthand) # add link += '&tierName=' + env.tier.name if environment_type: link += '&environmentType=' + environment_type if env.version_label: app_version = elasticbeanstalk.get_application_versions( app_name, version_labels=[env.version_label])['ApplicationVersions'][0] source_bundle = app_version['SourceBundle'] source_url = 'https://s3.amazonaws.com/' + source_bundle['S3Bucket'] + \ '/' + source_bundle['S3Key'] link += '&sourceBundleUrl=' + source_url if instance_type: link += '&instanceType=' + instance_type link = _add_database_options(link, option_settings) link = _add_vpc_options(link, option_settings) io.echo(link)
def stream_build_configuration_app_version_creation(app_name, app_version_label, build_spec): # Get the CloudWatch logs link successfully_generated = wait_for_app_version_attribute(app_name, [app_version_label], 'BuildArn', timeout=1) app_version_response = elasticbeanstalk.get_application_versions(app_name, version_labels=[app_version_label])['ApplicationVersions'] build_response = codebuild.batch_get_builds([app_version_response[0]['BuildArn']]) \ if successfully_generated else None codebuild_timeout = build_spec.timeout or 60 if build_response is not None and 'logs' in build_response['builds'][0]: log_link_text = strings['codebuild.buildlogs'].replace('{logs_link}', build_response['builds'][0]['logs']['deepLink']) io.echo(log_link_text) io.echo("NOTE: The CodeBuild timeout is set to {0} minutes, so this operation may take upto '{0}' minutes to complete.".format(codebuild_timeout)) else: io.log_warning("Could not retrieve CloudWatch link for CodeBuild logs") # Wait for the success events try: # Need to lazy-import `ebcli.lib.commonops` because `pytest` is unable to load it # at module load-time using Python 2.7 and Python 3.4 from ebcli.operations import commonops timeout_error_message = ' '.join([ 'The CodeBuild build timed out after {} minute(s).'.format(codebuild_timeout), "To increase the time limit, use the 'Timeout' option in the 'buildspec.yml' file." ]) commonops.wait_for_success_events( app_name=app_name, can_abort=False, request_id=None, timeout_error_message=timeout_error_message, timeout_in_minutes=codebuild_timeout, version_label=app_version_label ) except ServiceError as exception: LOG.debug("Caught service error while creating application version '{0}' " "deleting the created application version as it is useless now.".format(app_version_label)) elasticbeanstalk.delete_application_version(app_name, app_version_label) raise exception
def delete_app_version_label(app_name, version_label): if version_label: app_versions = elasticbeanstalk.get_application_versions( app_name)['ApplicationVersions'] if not any(version_label == app_version['VersionLabel'] for app_version in app_versions): raise ValidationError(strings['appversion.delete.notfound'].format( app_name, version_label)) envs = elasticbeanstalk.get_app_environments(app_name) versions_in_use = [(e.version_label, e.name) for e in envs] used_envs = [ version[1] for version in versions_in_use if version[0] == version_label ] if used_envs: raise ValidationError(strings['appversion.delete.deployed'].format( version_label, ','.join(used_envs))) should_delete = io.get_boolean_response( text=prompts['appversion.delete.validate'].format(version_label), default=True) if not should_delete: io.echo('Application Version will not be deleted.') delete_successful = False else: elasticbeanstalk.delete_application_version( app_name, version_label) io.echo('Application Version deleted successfully.') delete_successful = True return delete_successful else: raise NotFoundError(strings['appversion.delete.none'])
def wait_for_app_version_attribute(app_name, version_labels, attribute, timeout=5): versions_to_check = list(version_labels) found = {} failed = {} io.echo('--- Waiting for Application Versions to populate attributes ---') for version in version_labels: found[version] = False failed[version] = False start_time = datetime.utcnow() while not all([(found[version] or failed[version]) for version in versions_to_check]): if datetime.utcnow() - start_time >= timedelta(minutes=timeout): io.log_error(strings['appversion.attribute.failed'].replace('{app_version}', version_labels)) return False io.LOG.debug('Retrieving app versions.') app_versions = elasticbeanstalk.get_application_versions(app_name, versions_to_check)['ApplicationVersions'] for version in app_versions: if attribute in version: if version[attribute] is not None: found[version['VersionLabel']] = True io.echo(strings['appversion.attribute.success'].replace('{app_version}', version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) elif 'Status' in version and (version['Status'] == 'FAILED' or version['Status'] == 'FAILED'): failed[version['VersionLabel']] = True io.log_error(strings['appversion.attribute.failed'].replace('{app_version}', version['VersionLabel'])) versions_to_check.remove(version['VersionLabel']) if all(found.values()): return True time.sleep(4) if any(failed.values()): return False return True