Beispiel #1
0
def make_aws_credentials(config, role_arn=None, role_name=None):
    if role_arn:
        try:
            sts_connection = STSConnection()
            assumedRoleObject = sts_connection.assume_role(
                role_arn=role_arn,
                role_session_name=role_name
            )
        except:
            out("Oops! something went wrong trying to assume the specified role")
        else:
            # create credentials for switching roles
            aws = AwsCredentials(
                assumedRoleObject.credentials.access_key,
                assumedRoleObject.credentials.secret_key,
                assumedRoleObject.credentials.session_token,
                get(config, 'aws.region',           os.environ.get('AWS_DEFAULT_REGION')),
                get(config, 'aws.bucket',           os.environ.get('AWS_BEANSTALK_BUCKET_NAME')),
                get(config, 'aws.bucket_path',      os.environ.get('AWS_BEANSTALK_BUCKET_NAME_PATH')))
            out("Using Role: "+role_name)
    else:
        # create credentials
        aws = AwsCredentials(
            get(config, 'aws.access_key',       os.environ.get('AWS_ACCESS_KEY_ID')),
            get(config, 'aws.secret_key',       os.environ.get('AWS_SECRET_ACCESS_KEY')),
            get(config, 'aws.secret_token',     os.environ.get('AWS_SECRET_TOKEN')),
            get(config, 'aws.region',           os.environ.get('AWS_DEFAULT_REGION')),
            get(config, 'aws.bucket',           os.environ.get('AWS_BEANSTALK_BUCKET_NAME')),
            get(config, 'aws.bucket_path',      os.environ.get('AWS_BEANSTALK_BUCKET_NAME_PATH')))
    return aws
Beispiel #2
0
def run_ebs_deploy(command, args, parser=None):
    """
    the main
    """
    init_logging(args.use_logging)

    # make sure we have an archive or a directory
    if not args.config_file or not os.path.exists(args.config_file):
        out("Config file not found: " + args.config_file)
        parser and parser.print_help()
        return -1

    # make sure that if we have a role to assume, that we also have a role name to display
    if (args.role_arn and not args.role_name) or (args.role_name
                                                  and not args.role_arn):
        out("You must use and --role-arn and --role-name together")
        parser and parser.print_help()
        return -1

    # enable logging
    if args.verbose:
        from boto import set_stream_logger
        set_stream_logger('boto')

    config = load_config(args.config_file)
    aws = make_aws_credentials(config, args.role_arn, args.role_name)
    helper = EbsHelper(aws,
                       app_name=get(config, 'app.app_name'),
                       wait_time_secs=args.wait_time)

    # execute the command
    return command.execute(helper, config, args)
Beispiel #3
0
def run_ebs_deploy(command, args, parser=None):
    """
    the main
    """
    init_logging(args.use_logging)

    # make sure we have an archive or a directory
    if not args.config_file or not os.path.exists(args.config_file):
        out("Config file not found: "+args.config_file)
        parser and parser.print_help()
        return -1

    # make sure that if we have a role to assume, that we also have a role name to display
    if (args.role_arn and not args.role_name) or (args.role_name and not args.role_arn):
        out("You must use and --role-arn and --role-name together")
        parser and parser.print_help()
        return -1

    # enable logging
    if args.verbose:
        from boto import set_stream_logger
        set_stream_logger('boto')

    config = load_config(args.config_file)
    aws = make_aws_credentials(config, args.role_arn, args.role_name)
    helper = EbsHelper(aws, app_name=get(config, 'app.app_name'), wait_time_secs=args.wait_time)

    # execute the command
    return command.execute(helper, config, args)
Beispiel #4
0
def execute(helper, config, args):
    """
    dump command dumps things
    """
    settings = parse_option_settings(get(parse_env_config(config, args.environment), 'option_settings', []))
    for setting in settings:
        out(str(setting))
def execute(helper, config, args):
    """
    Lists solution stacks
    """
    out("Available solution stacks")
    for stack in helper.list_available_solution_stacks():
        out("    "+str(stack))
    return 0
Beispiel #6
0
def execute(helper, config, args):
    """
    Lists solution stacks
    """
    out("Available solution stacks")
    for stack in helper.list_available_solution_stacks():
        out("    " + str(stack))
    return 0
Beispiel #7
0
def execute(helper, config, args):
    """
    Lists environments
    """
    versions = helper.get_versions()
    out("Deployed versions:")
    for version in versions:
        out(version)
Beispiel #8
0
def execute(helper, config, args):
    """
    dump command dumps things
    """
    env = parse_env_config(config, args.environment)
    option_settings = env.get('option_settings', {})
    settings = parse_option_settings(option_settings)
    for setting in settings:
        out(str(setting))
Beispiel #9
0
def execute(helper, config, args):
    """
    dump command dumps things
    """
    env = parse_env_config(config, args.environment)
    option_settings = env.get('option_settings', {})
    settings = parse_option_settings(option_settings)
    for setting in settings:
        out(str(setting))
Beispiel #10
0
def execute(helper, config, args):
    """
    The init command
    """

    # check to see if the application exists
    if not helper.application_exists():
        helper.create_application(get(config, 'app.description'))
    else:
        out("Application "+get(config, 'app.app_name')+" exists")

    # create environments
    environment_names = []
    environments_to_wait_for_green = []
    for env_name, env_config in get(config, 'app.environments').items():
        environment_names.append(env_name)
        env_config = parse_env_config(config, env_name)
        actual_env_name = helper.environment_name_for_cname(env_config.get('cname_prefix', None))
        if not actual_env_name:
            option_settings = parse_option_settings(env_config.get('option_settings', {}))
            helper.create_environment(env_name,
                solution_stack_name=env_config.get('solution_stack_name'),
                cname_prefix=env_config.get('cname_prefix', None),
                description=env_config.get('description', None),
                option_settings=option_settings,
                tier_name=env_config.get('tier_name'),
                tier_type=env_config.get('tier_type'),
                tier_version=env_config.get('tier_version'))
            environments_to_wait_for_green.append(env_name)
        else:
            out("Environment "+env_name+" exists as "+actual_env_name)

    # get the environments
    environments_to_wait_for_term = []
    if args.delete:
        environments = helper.get_environments()
        for env in environments:
            if env['EnvironmentName'] not in environment_names:
                if env['Status'] != 'Ready':
                    out("Unable to delete "+env['EnvironmentName']+" because it's not in status Ready ("+env['Status']+")")
                else:
                    out("Deleting environment: "+env['EnvironmentName'])
                    helper.delete_environment(env['EnvironmentName'])
                    environments_to_wait_for_term.append(env['EnvironmentName'])

    # wait
    if not args.dont_wait and len(environments_to_wait_for_green)>0:
        helper.wait_for_environments(environments_to_wait_for_green, status='Ready', include_deleted=False)
    if not args.dont_wait and len(environments_to_wait_for_term)>0:
        helper.wait_for_environments(environments_to_wait_for_term, status='Terminated', include_deleted=False)

    out("Application initialized")
    return 0
def execute(helper, config, args):
    """
    Swaps old and new URLs.
    If old_environment was active, new_environment will become the active environment
    """
    old_env_name = args.old_environment
    new_env_name = args.new_environment

    # swap C-Names
    out("Assuming that {} is the currently active environment...".format(old_env_name))
    out("Swapping environment cnames: {} will become active, {} will become inactive.".format(new_env_name,
                                                                                              old_env_name))
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name], status='Ready', include_deleted=False)
def execute(helper, config, args):
    """
    Swaps old and new URLs.
    If old_environment was active, new_environment will become the active environment
    """
    old_env_name = args.old_environment
    new_env_name = args.new_environment

    # swap C-Names
    out("Assuming that {} is the currently active environment...".format(
        old_env_name))
    out("Swapping environment cnames: {} will become active, {} will become inactive."
        .format(new_env_name, old_env_name))
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name],
                                 status='Ready',
                                 include_deleted=False)
def execute(helper, config, args):
    """
    Lists environments
    """
    envs = config.get('app', {}).get('environments', [])
    out("Parsed environments:")
    for name, conf in list(envs.items()):
        out('\t'+name)
    envs = helper.get_environments()
    out("Deployed environments:")
    for env in envs:
        if env['Status'] != 'Terminated':
            out('\t'+str(env['EnvironmentName'])+' ('+str(env['Status'])+', '+str(env['CNAME'])+')')
def execute(helper, config, args):
    """
    Deletes an environment
    """

    env_config = parse_env_config(config, args.environment)
    environments_to_wait_for_term = []
    environments = helper.get_environments()

    for env in environments:
        if env['EnvironmentName'] == args.environment:
            if env['Status'] != 'Ready':
                out("Unable to delete " + env['EnvironmentName']
                    + " because it's not in status Ready ("
                    + env['Status'] + ")")
            else:
                out("Deleting environment: "+env['EnvironmentName'])
                helper.delete_environment(env['EnvironmentName'])
                environments_to_wait_for_term.append(env['EnvironmentName'])

    if not args.dont_wait:
        helper.wait_for_environments(environments_to_wait_for_term,
                                     status='Terminated',
                                     include_deleted=True)

    out("Environment deleted")
    return 0
Beispiel #15
0
def execute(helper, config, args):
    """
    Deletes an environment
    """

    env_config = parse_env_config(config, args.environment)
    environments_to_wait_for_term = []
    environments = helper.get_environments()

    for env in environments:
        if env['EnvironmentName'] == args.environment:
            if env['Status'] != 'Ready':
                out("Unable to delete " + env['EnvironmentName'] +
                    " because it's not in status Ready (" + env['Status'] +
                    ")")
            else:
                out("Deleting environment: " + env['EnvironmentName'])
                helper.delete_environment(env['EnvironmentName'])
                environments_to_wait_for_term.append(env['EnvironmentName'])

    if not args.dont_wait:
        helper.wait_for_environments(environments_to_wait_for_term,
                                     status='Terminated',
                                     include_deleted=True)

    out("Environment deleted")
    return 0
def execute(helper, config, args):
    """
    Lists environments
    """
    envs = config.get('app', {}).get('environments', [])
    out("Parsed environments:")
    for name, conf in envs.items():
        out('\t' + name)
    envs = helper.get_environments()
    out("Deployed environments:")
    for env in envs:
        if env['Status'] != 'Terminated':
            out('\t' + str(env['EnvironmentName']) + ' (' +
                str(env['Status']) + ', ' + str(env['CNAME']) + ')')
Beispiel #17
0
def make_aws_credentials(config, role_arn=None, role_name=None):
    if role_arn:
        try:
            sts_connection = STSConnection()
            assumedRoleObject = sts_connection.assume_role(
                role_arn=role_arn, role_session_name=role_name)
        except:
            out("Oops! something went wrong trying to assume the specified role"
                )
        else:
            # create credentials for switching roles
            aws = AwsCredentials(
                assumedRoleObject.credentials.access_key,
                assumedRoleObject.credentials.secret_key,
                assumedRoleObject.credentials.session_token,
                get(config, 'aws.region',
                    os.environ.get('AWS_DEFAULT_REGION')),
                get(config, 'aws.bucket',
                    os.environ.get('AWS_BEANSTALK_BUCKET_NAME')),
                get(config, 'aws.bucket_path',
                    os.environ.get('AWS_BEANSTALK_BUCKET_NAME_PATH')))
            out("Using Role: " + role_name)
    else:
        # create credentials
        aws = AwsCredentials(
            get(config, 'aws.access_key', os.environ.get('AWS_ACCESS_KEY_ID')),
            get(config, 'aws.secret_key',
                os.environ.get('AWS_SECRET_ACCESS_KEY')),
            get(config, 'aws.secret_token',
                os.environ.get('AWS_SECRET_TOKEN')),
            get(config, 'aws.region', os.environ.get('AWS_DEFAULT_REGION')),
            get(config, 'aws.bucket',
                os.environ.get('AWS_BEANSTALK_BUCKET_NAME')),
            get(config, 'aws.bucket_path',
                os.environ.get('AWS_BEANSTALK_BUCKET_NAME_PATH')))
    return aws
def execute(helper, config, args):
    """
    Deploys to an environment
    """
    version_label = args.version_label
    archive = args.archive

    # get the environment configuration
    env_config = parse_env_config(config, args.environment)
    option_settings = parse_option_settings(env_config.get('option_settings', {}))
    cname_prefix = env_config.get('cname_prefix', None)

    # no zdt for anything but web server
    tier_name = env_config.get('tier_name', 'WebServer')
    if tier_name != 'WebServer':
        raise Exception(
            "Only able to do zero downtime deployments for "
            "WebServer tiers, can't do them for %s" % (tier_name, ))

    # find an available environment name
    out("Determining new environment name...")
    new_env_name = None
    if not helper.environment_exists(args.environment, include_deleted=True):
        new_env_name = args.environment
    else:
        for i in xrange(10):
            temp_env_name = args.environment + '-' + str(i)
            if not helper.environment_exists(temp_env_name, include_deleted=True):
                new_env_name = temp_env_name
                break
    if new_env_name is None:
        raise Exception("Unable to determine new environment name")
    else:
        out("New environment name will be " + new_env_name)

    # find an available cname name
    new_env_cname = cname_prefix + "-" + uuid4().hex[:8]
    out("New environment cname will be " + new_env_cname)

    # find existing environment name
    old_env_name = helper.get_previous_environment_for_subdomain(cname_prefix)

    min_size = None
    max_size = None
    desired_capacity = None

    if old_env_name:
        min_size, max_size, desired_capacity = helper.get_env_sizing_metrics(old_env_name)
        out("Retrieved old cluster sizes from {}: MinSize - {}, MaxSize - {}, DesiredCapacity - {}".format(
            old_env_name, min_size, max_size, desired_capacity))

    should_copy_scaling_sizes = args.copy_previous_size and desired_capacity and max_size and min_size

    if should_copy_scaling_sizes:
        # We want the new cluster to start up with `desired_capacity` instances,
        # so set its min_size to that value. Later, we will adjust.
        option_settings = override_scaling(option_settings, desired_capacity, max_size)
        out("Overriding new cluster sizes: MinSize - {}, MaxSize - {}".format(
            desired_capacity, max_size))


    # upload or build an archive
    version_label = upload_application_archive(
        helper, env_config, archive=args.archive, directory=args.directory, version_label=version_label)

    # create the new environment
    helper.create_environment(new_env_name,
                              solution_stack_name=env_config.get('solution_stack_name'),
                              cname_prefix=new_env_cname,
                              description=env_config.get('description', None),
                              option_settings=option_settings,
                              version_label=version_label,
                              tier_name=tier_name,
                              tier_type=env_config.get('tier_type'),
                              tier_version=env_config.get('tier_version'))
    helper.wait_for_environments(new_env_name, status='Ready', health='Green', include_deleted=False)

    if old_env_name is None:
        raise Exception("Unable to find current environment with cname: " + cname_prefix)
    out("Current environment name is " + old_env_name)

    env_data = helper.environment_data(new_env_name)

    if args.check_command:
        if callable(args.check_command):
            out("Running check-command function")
            args.check_command(env_data)
            out("check-command passed")
        elif isinstance(args.check_command, basestring):
            command = shlex.split(args.check_command) + [new_env_cname]
            out("Running check-command {}".format(command))
            rc = sh.Command(command[0])(command[1:], _iter=True)
            for line in rc:
                out(line.rstrip())
            out("Exit Code: {}".format(rc.exit_code))

    # we need to readjust the min_size of the new cluster, because it's currently set to the old cluster's
    # desired_capacity
    if should_copy_scaling_sizes and desired_capacity != min_size:
        helper.set_env_sizing_metrics(new_env_name, min_size, max_size)
        out("Resizing new cluster MinSize to {}".format(min_size))
        helper.wait_for_environments(new_env_name, status='Ready', health='Green', include_deleted=False)

    # swap C-Names
    out("Swapping environment cnames")
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name], status='Ready', include_deleted=False)

    # delete the old environment
    if args.termination_delay:
        out("Termination delay specified, sleeping for {} seconds...".format(args.termination_delay))
        time.sleep(args.termination_delay)
    out("Deleting old environment {}".format(old_env_name))
    helper.delete_environment(old_env_name)

    # delete unused
    helper.delete_unused_versions(versions_to_keep=int(get(config, 'app.versions_to_keep', 10)))
Beispiel #19
0
def usage():
    commands = get_command_names()
    out("usage: ebs-deploy command [options | help]")
    out("Where command is one of:")
    for cmd in commands:
        out("    " + cmd)
Beispiel #20
0
def execute(helper, config, args):
    """
    Deploys to an environment
    """
    version_label = args.version_label
    archive = args.archive

    # get the environment configuration
    env_config = parse_env_config(config, args.environment)
    option_settings = parse_option_settings(env_config.get('option_settings', {}))
    cname_prefix = env_config.get('cname_prefix', None)

    # no zdt for anything but web server
    tier_name = env_config.get('tier_name', 'WebServer')
    if tier_name != 'WebServer':
        raise Exception(
            "Only able to do zero downtime deployments for "
            "WebServer tiers, can't do them for %s" % (tier_name, ))

    # find existing environment name
    old_env_name = helper.environment_name_for_cname(cname_prefix)
    if old_env_name is None:
        raise Exception("Unable to find current environment with cname: " + cname_prefix)
    out("Current environment name is " + old_env_name)

    # find an available environment name
    out("Determining new environment name...")
    new_env_name = None
    if not helper.environment_exists(args.environment):
        new_env_name = args.environment
    else:
        for i in xrange(10):
            temp_env_name = args.environment + '-' + str(i)
            if not helper.environment_exists(temp_env_name):
                new_env_name = temp_env_name
                break
    if new_env_name is None:
        raise Exception("Unable to determine new environment name")
    out("New environment name will be " + new_env_name)

    # find an available cname name
    out("Determining new environment cname...")
    new_env_cname = None
    for i in xrange(10):
        temp_cname = cname_prefix + '-' + str(i)
        if not helper.environment_name_for_cname(temp_cname):
            new_env_cname = temp_cname
            break
    if new_env_cname is None:
        raise Exception("Unable to determine new environment cname")
    out("New environment cname will be " + new_env_cname)

    # upload or build an archive
    version_label = upload_application_archive(
        helper, env_config, archive=args.archive, directory=args.directory, version_label=version_label)

    # create the new environment
    helper.create_environment(new_env_name,
                              solution_stack_name=env_config.get('solution_stack_name'),
                              cname_prefix=new_env_cname,
                              description=env_config.get('description', None),
                              option_settings=option_settings,
                              version_label=version_label,
                              tier_name=tier_name,
                              tier_type=env_config.get('tier_type'),
                              tier_version=env_config.get('tier_version'))
    helper.wait_for_environments(new_env_name, status='Ready', health='Green', include_deleted=False)

    # swap C-Names
    out("Swapping environment cnames")
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name], status='Ready', include_deleted=False)

    # delete the old environment
    if args.termination_delay:
        out("Termination delay specified, sleeping for {} seconds...".format(args.termination_delay))
        time.sleep(args.termination_delay)
    helper.delete_environment(old_env_name)

    # delete unused
    helper.delete_unused_versions(versions_to_keep=int(get(config, 'app.versions_to_keep', 10)))
Beispiel #21
0
def execute(helper, config, args):
    """
    Deploys to an environment
    """
    version_label = args.version_label
    archive = args.archive

    # get the environment configuration
    env_config = parse_env_config(config, args.environment)
    option_settings = parse_option_settings(
        env_config.get('option_settings', {}))
    cname_prefix = env_config.get('cname_prefix', None)

    # no zdt for anything but web server
    tier_name = env_config.get('tier_name', 'WebServer')
    if tier_name != 'WebServer':
        raise Exception("Only able to do zero downtime deployments for "
                        "WebServer tiers, can't do them for %s" %
                        (tier_name, ))

    # find existing environment name
    old_env_name = helper.environment_name_for_cname(cname_prefix)
    if old_env_name is None:
        raise Exception("Unable to find current environment with cname: " +
                        cname_prefix)
    out("Current environment name is " + old_env_name)

    # find an available environment name
    out("Determining new environment name...")
    new_env_name = None
    if not helper.environment_exists(args.environment):
        new_env_name = args.environment
    else:
        for i in xrange(10):
            temp_env_name = args.environment + '-' + str(i)
            if not helper.environment_exists(temp_env_name):
                new_env_name = temp_env_name
                break
    if new_env_name is None:
        raise Exception("Unable to determine new environment name")
    out("New environment name will be " + new_env_name)

    # find an available cname name
    out("Determining new environment cname...")
    new_env_cname = None
    for i in xrange(10):
        temp_cname = cname_prefix + '-' + str(i)
        if not helper.environment_name_for_cname(temp_cname):
            new_env_cname = temp_cname
            break
    if new_env_cname is None:
        raise Exception("Unable to determine new environment cname")
    out("New environment cname will be " + new_env_cname)

    # upload or build an archive
    version_label = upload_application_archive(helper,
                                               env_config,
                                               archive=args.archive,
                                               directory=args.directory,
                                               version_label=version_label)

    # create the new environment
    helper.create_environment(
        new_env_name,
        solution_stack_name=env_config.get('solution_stack_name'),
        cname_prefix=new_env_cname,
        description=env_config.get('description', None),
        option_settings=option_settings,
        version_label=version_label,
        tier_name=tier_name,
        tier_type=env_config.get('tier_type'),
        tier_version=env_config.get('tier_version'))
    helper.wait_for_environments(new_env_name,
                                 status='Ready',
                                 health='Green',
                                 include_deleted=False)

    # swap C-Names
    out("Swapping environment cnames")
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name],
                                 status='Ready',
                                 include_deleted=False)

    # delete the old environment
    if args.termination_delay:
        out("Termination delay specified, sleeping for {} seconds...".format(
            args.termination_delay))
        time.sleep(args.termination_delay)
    helper.delete_environment(old_env_name)

    # delete unused
    helper.delete_unused_versions(
        versions_to_keep=int(get(config, 'app.versions_to_keep', 10)))
Beispiel #22
0
def execute(helper, config, args):
    """
    The init command
    """

    # check to see if the application exists
    if not helper.application_exists():
        helper.create_application(get(config, "app.description"))
    else:
        out("Application " + get(config, "app.app_name") + " exists")

    # create environments
    environment_names = []
    environments_to_wait_for_green = []
    for env_name, env_config in get(config, "app.environments").items():
        environment_names.append(env_name)
        env_config = parse_env_config(config, env_name)
        if not helper.environment_exists(env_name):
            option_settings = parse_option_settings(env_config.get("option_settings", {}))
            helper.create_environment(
                env_name,
                solution_stack_name=env_config.get("solution_stack_name"),
                cname_prefix=env_config.get("cname_prefix", None),
                description=env_config.get("description", None),
                option_settings=option_settings,
                tier_name=env_config.get("tier_name"),
                tier_type=env_config.get("tier_type"),
                tier_version=env_config.get("tier_version"),
                version_label=args.version_label,
            )
            environments_to_wait_for_green.append(env_name)
        else:
            out("Environment " + env_name)

    # get the environments
    environments_to_wait_for_term = []
    if args.delete:
        environments = helper.get_environments()
        for env in environments:
            if env["EnvironmentName"] not in environment_names:
                if env["Status"] != "Ready":
                    out(
                        "Unable to delete "
                        + env["EnvironmentName"]
                        + " because it's not in status Ready ("
                        + env["Status"]
                        + ")"
                    )
                else:
                    out("Deleting environment: " + env["EnvironmentName"])
                    helper.delete_environment(env["EnvironmentName"])
                    environments_to_wait_for_term.append(env["EnvironmentName"])

    # wait
    if not args.dont_wait and len(environments_to_wait_for_green) > 0:
        helper.wait_for_environments(environments_to_wait_for_green, status="Ready", include_deleted=False)
    if not args.dont_wait and len(environments_to_wait_for_term) > 0:
        helper.wait_for_environments(environments_to_wait_for_term, status="Terminated", include_deleted=False)

    out("Application initialized")
    return 0
Beispiel #23
0
def usage():
    commands = get_command_names()
    out("usage: ebs-deploy command [options | help]")
    out("Where command is one of:")
    for cmd in commands:
        out("    "+cmd)
def execute(helper, config, args):
    """
    Deploys to an environment
    """
    version_label = args.version_label
    archive = args.archive

    # get the environment configuration
    env_config = parse_env_config(config, args.environment)
    option_settings = parse_option_settings(env_config.get('option_settings', {}))
    cname_prefix = env_config.get('cname_prefix', None)

    # find existing environment name
    old_env_name = helper.environment_name_for_cname(cname_prefix)
    if old_env_name is None:
        raise Exception("Unable to find current environment with cname: "+cname_prefix)
    out("Current environment name is "+old_env_name)

    # find an available environment name
    out("Determining new environment name...")
    new_env_name = None
    if not helper.environment_exists(args.environment):
        new_env_name = args.environment
    else:
        for i in xrange(10):
            temp_env_name = args.environment+'-'+str(i)
            if not helper.environment_exists(temp_env_name):
                new_env_name = temp_env_name
                break
    if new_env_name is None:
        raise Exception("Unable to determine new environment name")
    out("New environment name will be "+new_env_name)

    # find an available cname name
    out("Determining new environment cname...")
    new_env_cname = None
    for i in xrange(10):
        temp_cname = cname_prefix+'-'+str(i)
        if not helper.environment_name_for_cname(temp_cname):
            new_env_cname = temp_cname
            break
    if new_env_cname is None:
        raise Exception("Unable to determine new environment cname")
    out("New environment cname will be "+new_env_cname)

    # upload or build an archive
    version_label = upload_application_archive(
        helper, env_config, archive=args.archive, directory=args.directory, version_label=version_label)

    # create the new environment
    helper.create_environment(new_env_name,
        solution_stack_name=env_config.get('solution_stack_name'),
        cname_prefix=new_env_cname,
        description=env_config.get('description', None),
        option_settings=option_settings,
        version_label=version_label)
    helper.wait_for_environments(new_env_name, status='Ready', health='Green', include_deleted=False)

    # swap C-Names
    out("Swapping environment cnames")
    helper.swap_environment_cnames(old_env_name, new_env_name)
    helper.wait_for_environments([old_env_name, new_env_name], status='Ready', include_deleted=False)

    # delete the old environmnet
    helper.delete_environment(old_env_name)

    # delete unused
    helper.delete_unused_versions(versions_to_keep=int( get(config, 'app.versions_to_keep', 10) ))