<s> from boto . exception import S3ResponseError <EOL> from boto . s3 . connection import S3Connection <EOL> from boto . beanstalk import connect_to_region <EOL> from boto . s3 . key import Key <EOL> from datetime import datetime <EOL> from time import time , sleep <EOL> import zipfile <EOL> import os <EOL> import subprocess <EOL> import sys <EOL> import yaml <EOL> import re <EOL> def out ( message ) : <EOL> """<STR_LIT>""" <EOL> sys . stdout . write ( message + "<STR_LIT:\n>" ) <EOL> sys . stdout . flush ( ) <EOL> def merge_dict ( dict1 , dict2 ) : <EOL> ret = dict ( dict2 ) <EOL> for key , val in dict1 . items ( ) : <EOL> val2 = dict2 . get ( key ) <EOL> if val2 is None : <EOL> ret [ key ] = val <EOL> elif isinstance ( val , dict ) and isinstance ( val2 , dict ) : <EOL> ret [ key ] = merge_dict ( val , val2 ) <EOL> elif isinstance ( val , ( list ) ) and isinstance ( val2 , ( list ) ) : <EOL> ret [ key ] = val + val2 <EOL> else : <EOL> ret [ key ] = val2 <EOL> return ret <EOL> def get ( vals , key , default_val = None ) : <EOL> """<STR_LIT>""" <EOL> val = vals <EOL> for part in key . split ( '<STR_LIT:.>' ) : <EOL> if isinstance ( val , dict ) : <EOL> val = val . get ( part , None ) <EOL> if val is None : <EOL> return default_val <EOL> else : <EOL> return default_val <EOL> return val <EOL> def parse_option_settings ( option_settings ) : <EOL> """<STR_LIT>""" <EOL> ret = [ ] <EOL> for namespace , params in option_settings . items ( ) : <EOL> for key , value in params . items ( ) : <EOL> ret . append ( ( namespace , key , value ) ) <EOL> return ret <EOL> def parse_env_config ( config , env_name ) : <EOL> """<STR_LIT>""" <EOL> all_env = get ( config , '<STR_LIT>' , { } ) <EOL> env = get ( config , '<STR_LIT>' + str ( env_name ) , { } ) <EOL> return merge_dict ( all_env , env ) <EOL> def upload_application_archive ( helper , env_config , archive = None , directory = None , version_label = None ) : <EOL> if version_label is None : <EOL> version_label = datetime . now ( ) . strftime ( '<STR_LIT>' ) <EOL> archive_file_name = None <EOL> if archive : <EOL> archive_file_name = os . path . basename ( archive ) <EOL> archive_files = get ( env_config , '<STR_LIT>' , [ ] ) <EOL> if get ( env_config , '<STR_LIT>' ) : <EOL> cmd = get ( env_config , '<STR_LIT>' ) <EOL> output_file = get ( env_config , '<STR_LIT>' ) <EOL> use_shell = get ( env_config , '<STR_LIT>' , True ) <EOL> exit_code = get ( env_config , '<STR_LIT>' , <NUM_LIT:0> ) <EOL> if not cmd or not output_file : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> output_regex = None <EOL> try : <EOL> output_regex = re . compile ( output_file ) <EOL> except : <EOL> pass <EOL> result = subprocess . call ( cmd , shell = use_shell ) <EOL> if result != exit_code : <EOL> raise Exception ( '<STR_LIT>' % ( result , exit_code ) ) <EOL> if output_file and os . path . exists ( output_file ) : <EOL> archive_file_name = os . path . basename ( output_file ) <EOL> else : <EOL> for root , dirs , files in os . walk ( "<STR_LIT:.>" , followlinks = True ) : <EOL> for f in files : <EOL> fullpath = os . path . join ( root , f ) <EOL> if fullpath . endswith ( output_file ) : <EOL> archive = fullpath <EOL> archive_file_name = os . path . basename ( fullpath ) <EOL> break <EOL> elif output_regex and output_regex . match ( fullpath ) : <EOL> archive = fullpath <EOL> archive_file_name = os . path . basename ( fullpath ) <EOL> break <EOL> if archive : <EOL> break <EOL> if not archive or not archive_file_name : <EOL> raise Exception ( '<STR_LIT>' % ( output_file ) ) <EOL> elif not archive : <EOL> if not directory : <EOL> directory = "<STR_LIT:.>" <EOL> includes = get ( env_config , '<STR_LIT>' , [ ] ) <EOL> excludes = get ( env_config , '<STR_LIT>' , [ ] ) <EOL> def _predicate ( f ) : <EOL> for exclude in excludes : <EOL> if re . match ( exclude , f ) : <EOL> return False <EOL> if len ( includes ) > <NUM_LIT:0> : <EOL> for include in includes : <EOL> if re . match ( include , f ) : <EOL> return True <EOL> return False <EOL> return True <EOL> archive = create_archive ( directory , str ( version_label ) + "<STR_LIT>" , config = archive_files , ignore_predicate = _predicate ) <EOL> archive_file_name = str ( version_label ) + "<STR_LIT>" <EOL> add_config_files_to_archive ( directory , archive , config = archive_files ) <EOL> helper . upload_archive ( archive , archive_file_name ) <EOL> helper . create_application_version ( version_label , archive_file_name ) <EOL> return version_label <EOL> def create_archive ( directory , filename , config = { } , ignore_predicate = None , ignored_files = [ '<STR_LIT>' , '<STR_LIT>' ] ) : <EOL> """<STR_LIT>""" <EOL> with zipfile . ZipFile ( filename , '<STR_LIT:w>' , compression = zipfile . ZIP_DEFLATED ) as zip_file : <EOL> root_len = len ( os . path . abspath ( directory ) ) <EOL> out ( "<STR_LIT>" + str ( filename ) ) <EOL> for root , dirs , files in os . walk ( directory , followlinks = True ) : <EOL> archive_root = os . path . abspath ( root ) [ root_len + <NUM_LIT:1> : ] <EOL> for f in files : <EOL> fullpath = os . path . join ( root , f ) <EOL> archive_name = os . path . join ( archive_root , f ) <EOL> if filename in fullpath : <EOL> continue <EOL> if ignored_files is not None : <EOL> for name in ignored_files : <EOL> if fullpath . endswith ( name ) : <EOL> out ( "<STR_LIT>" + str ( name ) ) <EOL> continue <EOL> if ignore_predicate is not None : <EOL> if not ignore_predicate ( archive_name ) : <EOL> out ( "<STR_LIT>" + str ( archive_name ) ) <EOL> continue <EOL> out ( "<STR_LIT>" + str ( archive_name ) ) <EOL> zip_file . write ( fullpath , archive_name , zipfile . ZIP_DEFLATED ) <EOL> return filename <EOL> def add_config_files_to_archive ( directory , filename , config = { } ) : <EOL> """<STR_LIT>""" <EOL> with zipfile . ZipFile ( filename , '<STR_LIT:a>' ) as zip_file : <EOL> for conf in config : <EOL> for conf , tree in conf . items ( ) : <EOL> if tree . has_key ( '<STR_LIT>' ) : <EOL> content = yaml . dump ( tree [ '<STR_LIT>' ] , default_flow_style = False ) <EOL> else : <EOL> content = tree . get ( '<STR_LIT:content>' , '<STR_LIT>' ) <EOL> out ( "<STR_LIT>" + str ( conf ) + "<STR_LIT>" + str ( filename ) ) <EOL> file_entry = zipfile . ZipInfo ( conf ) <EOL> file_entry . external_attr = tree . get ( '<STR_LIT>' , <NUM_LIT:0> <NUM_LIT> ) << <NUM_LIT:16> L <EOL> zip_file . writestr ( file_entry , content ) <EOL> return filename <EOL> class AwsCredentials : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , access_key , secret_key , security_token , region , bucket , bucket_path ) : <EOL> self . access_key = access_key <EOL> self . secret_key = secret_key <EOL> self . security_token = security_token <EOL> self . bucket = bucket <EOL> self . region = region <EOL> self . bucket_path = bucket_path <EOL> if not self . bucket_path . endswith ( '<STR_LIT:/>' ) : <EOL> self . bucket_path += '<STR_LIT:/>' <EOL> class EbsHelper ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , aws , wait_time_secs , app_name = None , ) : <EOL> """<STR_LIT>""" <EOL> self . aws = aws <EOL> self . ebs = connect_to_region ( aws . region , aws_access_key_id = aws . access_key , <EOL> aws_secret_access_key = aws . secret_key , <EOL> security_token = aws . security_token ) <EOL> self . s3 = S3Connection ( <EOL> aws_access_key_id = aws . access_key , <EOL> aws_secret_access_key = aws . secret_key , <EOL> security_token = aws . security_token , <EOL> host = ( lambda r : '<STR_LIT>' if r == '<STR_LIT>' else '<STR_LIT>' + r + '<STR_LIT>' ) ( aws . region ) ) <EOL> self . app_name = app_name <EOL> self . wait_time_secs = wait_time_secs <EOL> def swap_environment_cnames ( self , from_env_name , to_env_name ) : <EOL> """<STR_LIT>""" <EOL> self . ebs . swap_environment_cnames ( source_environment_name = from_env_name , <EOL> destination_environment_name = to_env_name ) <EOL> def upload_archive ( self , filename , key , auto_create_bucket = True ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> bucket = self . s3 . get_bucket ( self . aws . bucket ) <EOL> if ( ( <EOL> self . aws . region != '<STR_LIT>' and self . aws . region != '<STR_LIT>' ) and bucket . get_location ( ) != self . aws . region ) or ( <EOL> self . aws . region == '<STR_LIT>' and bucket . get_location ( ) != '<STR_LIT>' ) or ( <EOL> self . aws . region == '<STR_LIT>' and bucket . get_location ( ) != '<STR_LIT>' ) : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> except S3ResponseError : <EOL> bucket = self . s3 . create_bucket ( self . aws . bucket , location = self . aws . region ) <EOL> def __report_upload_progress ( sent , total ) : <EOL> if not sent : <EOL> sent = <NUM_LIT:0> <EOL> if not total : <EOL> total = <NUM_LIT:0> <EOL> out ( "<STR_LIT>" + str ( sent ) + "<STR_LIT>" + str ( total ) + "<STR_LIT>" + str ( int ( float ( max ( <NUM_LIT:1> , sent ) ) / float ( total ) * <NUM_LIT:100> ) ) + "<STR_LIT>" ) <EOL> k = Key ( bucket ) <EOL> k . key = self . aws . bucket_path + key <EOL> k . set_metadata ( '<STR_LIT:time>' , str ( time ( ) ) ) <EOL> k . set_contents_from_filename ( filename , cb = __report_upload_progress , num_cb = <NUM_LIT:10> ) <EOL> def list_available_solution_stacks ( self ) : <EOL> """<STR_LIT>""" <EOL> stacks = self . ebs . list_available_solution_stacks ( ) <EOL> return stacks [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> def create_application ( self , description = None ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( self . app_name ) ) <EOL> self . ebs . create_application ( self . app_name , description = description ) <EOL> def delete_application ( self ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( self . app_name ) ) <EOL> self . ebs . delete_application ( self . app_name , terminate_env_by_force = True ) <EOL> def application_exists ( self ) : <EOL> """<STR_LIT>""" <EOL> response = self . ebs . describe_applications ( application_names = [ self . app_name ] ) <EOL> return len ( response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) > <NUM_LIT:0> <EOL> def create_environment ( self , env_name , version_label = None , <EOL> solution_stack_name = None , cname_prefix = None , description = None , <EOL> option_settings = None , tier_name = '<STR_LIT>' , tier_type = '<STR_LIT>' , tier_version = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( env_name ) + "<STR_LIT>" + str ( tier_name ) + "<STR_LIT>" + str ( tier_type ) ) <EOL> self . ebs . create_environment ( self . app_name , env_name , <EOL> version_label = version_label , <EOL> solution_stack_name = solution_stack_name , <EOL> cname_prefix = cname_prefix , <EOL> description = description , <EOL> option_settings = option_settings , <EOL> tier_type = tier_type , <EOL> tier_name = tier_name , <EOL> tier_version = tier_version ) <EOL> def environment_exists ( self , env_name ) : <EOL> """<STR_LIT>""" <EOL> response = self . ebs . describe_environments ( application_name = self . app_name , environment_names = [ env_name ] , <EOL> include_deleted = False ) <EOL> return len ( response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) > <NUM_LIT:0> and response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ <NUM_LIT:0> ] [ <EOL> '<STR_LIT>' ] != '<STR_LIT>' <EOL> def rebuild_environment ( self , env_name ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( env_name ) ) <EOL> self . ebs . rebuild_environment ( environment_name = env_name ) <EOL> def get_environments ( self ) : <EOL> """<STR_LIT>""" <EOL> response = self . ebs . describe_environments ( application_name = self . app_name , include_deleted = False ) <EOL> return response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> def delete_environment ( self , environment_name ) : <EOL> """<STR_LIT>""" <EOL> self . ebs . terminate_environment ( environment_name = environment_name , terminate_resources = True ) <EOL> def update_environment ( self , environment_name , description = None , option_settings = [ ] , tier_type = None , tier_name = None , <EOL> tier_version = '<STR_LIT:1.0>' ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( environment_name ) ) <EOL> messages = self . ebs . validate_configuration_settings ( self . app_name , option_settings , <EOL> environment_name = environment_name ) <EOL> messages = messages [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> ok = True <EOL> for message in messages : <EOL> if message [ '<STR_LIT>' ] == '<STR_LIT:error>' : <EOL> ok = False <EOL> out ( "<STR_LIT:[>" + message [ '<STR_LIT>' ] + "<STR_LIT>" + str ( environment_name ) + "<STR_LIT>" + message [ '<STR_LIT>' ] + "<STR_LIT::>" + message [ '<STR_LIT>' ] + "<STR_LIT>" + message [ '<STR_LIT>' ] ) <EOL> self . ebs . update_environment ( <EOL> environment_name = environment_name , <EOL> description = description , <EOL> option_settings = option_settings , <EOL> tier_type = tier_type , <EOL> tier_name = tier_name , <EOL> tier_version = tier_version ) <EOL> def environment_name_for_cname ( self , env_cname ) : <EOL> """<STR_LIT>""" <EOL> envs = self . get_environments ( ) <EOL> for env in envs : <EOL> if env [ '<STR_LIT>' ] != '<STR_LIT>' and env . has_key ( '<STR_LIT>' ) and env [ '<STR_LIT>' ] and env [ '<STR_LIT>' ] . lower ( ) . startswith ( env_cname . lower ( ) + '<STR_LIT:.>' ) : <EOL> return env [ '<STR_LIT>' ] <EOL> return None <EOL> def deploy_version ( self , environment_name , version_label ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( version_label ) + "<STR_LIT>" + str ( environment_name ) ) <EOL> self . ebs . update_environment ( environment_name = environment_name , version_label = version_label ) <EOL> def get_versions ( self ) : <EOL> """<STR_LIT>""" <EOL> response = self . ebs . describe_application_versions ( application_name = self . app_name ) <EOL> return response [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> def create_application_version ( self , version_label , key ) : <EOL> """<STR_LIT>""" <EOL> out ( "<STR_LIT>" + str ( version_label ) + "<STR_LIT>" + str ( key ) ) <EOL> self . ebs . create_application_version ( self . app_name , version_label , <EOL> s3_bucket = self . aws . bucket , s3_key = self . aws . bucket_path + key ) <EOL> def delete_unused_versions ( self , versions_to_keep = <NUM_LIT:10> ) : <EOL> """<STR_LIT>""" <EOL> environments = self . ebs . describe_environments ( application_name = self . app_name , include_deleted = False ) <EOL> environments = environments [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> versions_in_use = [ ] <EOL> for env in environments : <EOL> versions_in_use . append ( env [ '<STR_LIT>' ] ) <EOL> versions = self . ebs . describe_application_versions ( application_name = self . app_name ) <EOL> versions = versions [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ <EOL> '<STR_LIT>' ] <EOL> versions = sorted ( versions , reverse = True , cmp = lambda x , y : cmp ( x [ '<STR_LIT>' ] , y [ '<STR_LIT>' ] ) ) <EOL> for version in versions [ versions_to_keep : ] : <EOL> if version [ '<STR_LIT>' ] in versions_in_use : <EOL> out ( "<STR_LIT>" + version [ "<STR_LIT>" ] + "<STR_LIT>" ) <EOL> else : <EOL> out ( "<STR_LIT>" + version [ "<STR_LIT>" ] ) <EOL> self . ebs . delete_application_version ( application_name = self . app_name , <EOL> version_label = version [ '<STR_LIT>' ] ) <EOL> sleep ( <NUM_LIT:2> ) <EOL> def describe_events ( self , environment_name , next_token = None , start_time = None ) : <EOL> """<STR_LIT>""" <EOL> events = self . ebs . describe_events ( <EOL> application_name = self . app_name , <EOL> environment_name = environment_name , <EOL> next_token = next_token , <EOL> start_time = start_time ) <EOL> return ( events [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] , events [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) <EOL> def wait_for_environments ( self , environment_names , health = None , status = None , version_label = None , <EOL> include_deleted = True , use_events = True ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( environment_names , ( list , tuple ) ) : <EOL> environment_names = [ environment_names ] <EOL> environment_names = environment_names [ : ] <EOL> s = "<STR_LIT>" + ( "<STR_LIT:U+002CU+0020>" . join ( environment_names ) ) + "<STR_LIT>" <EOL> if health is not None : <EOL> s += "<STR_LIT>" + health <EOL> else : <EOL> s += "<STR_LIT>" <EOL> if version_label is not None : <EOL> s += "<STR_LIT>" + version_label <EOL> if status is not None : <EOL> s += "<STR_LIT>" + status <EOL> out ( s ) <EOL> started = time ( ) <EOL> seen_events = list ( ) <EOL> for env_name in environment_names : <EOL> ( events , next_token ) = self . describe_events ( env_name , start_time = datetime . now ( ) . isoformat ( ) ) <EOL> for event in events : <EOL> seen_events . append ( event ) <EOL> while True : <EOL> if len ( environment_names ) == <NUM_LIT:0> : <EOL> break <EOL> sleep ( <NUM_LIT:5> ) <EOL> environments = self . ebs . describe_environments ( <EOL> application_name = self . app_name , <EOL> environment_names = environment_names , <EOL> include_deleted = include_deleted ) <EOL> environments = environments [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> if len ( environments ) <= <NUM_LIT:0> : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> for env in environments [ : ] : <EOL> env_name = env [ '<STR_LIT>' ] <EOL> msg = "<STR_LIT>" + env_name + "<STR_LIT>" + str ( env [ '<STR_LIT>' ] ) <EOL> if version_label is not None : <EOL> msg = msg + "<STR_LIT>" + str ( env [ '<STR_LIT>' ] ) <EOL> if status is not None : <EOL> msg = msg + "<STR_LIT>" + str ( env [ '<STR_LIT>' ] ) <EOL> good_to_go = True <EOL> if health is not None : <EOL> good_to_go = good_to_go and str ( env [ '<STR_LIT>' ] ) == health <EOL> if status is not None : <EOL> good_to_go = good_to_go and str ( env [ '<STR_LIT>' ] ) == status <EOL> if version_label is not None : <EOL> good_to_go = good_to_go and str ( env [ '<STR_LIT>' ] ) == version_label <EOL> if good_to_go : <EOL> out ( msg + "<STR_LIT>" ) <EOL> environment_names . remove ( env_name ) <EOL> else : <EOL> out ( msg + "<STR_LIT>" ) <EOL> ( events , next_token ) = self . describe_events ( env_name , start_time = datetime . now ( ) . isoformat ( ) ) <EOL> for event in events : <EOL> if event not in seen_events : <EOL> out ( "<STR_LIT:[>" + event [ '<STR_LIT>' ] + "<STR_LIT>" + event [ '<STR_LIT>' ] ) <EOL> seen_events . append ( event ) <EOL> elapsed = time ( ) - started <EOL> if elapsed > self . wait_time_secs : <EOL> message = "<STR_LIT>" . format ( <EOL> environments = "<STR_LIT>" . join ( environment_names ) , health = ( health or "<STR_LIT>" ) <EOL> ) <EOL> raise Exception ( message ) </s>
