Exemple #1
0
def get_or_create_eb_application():
    """
    https://docs.aws.amazon.com/elasticbeanstalk/latest/api/API_CreateApplication.html
    """
    eb_client = create_eb_client()

    applications = eb_client.describe_applications().get('Applications', None)
    for app in applications:
        app_name = app.get('ApplicationName', None)
        if app_name and BEIWE_APPLICATION_NAME.lower() in app_name.lower():
            log.info('Using Elastic Beanstalk application named "%s."' %
                     app_name)
            return BEIWE_APPLICATION_NAME

    # raise Exception("no beiwe applications found")
    _ = eb_client.create_application(
        ApplicationName=BEIWE_APPLICATION_NAME,
        Description='Your Beiwe Application',
        ResourceLifecycleConfig={
            'ServiceRole': get_or_create_automation_policy()['Arn'],
            # The ARN of an IAM service role that Elastic Beanstalk has permission to assume
            'VersionLifecycleConfig': {
                'MaxCountRule': {
                    'Enabled': False,
                    'MaxCount': 1000,  # should be ignored
                    'DeleteSourceFromS3': True
                },
                'MaxAgeRule': {
                    'Enabled': False,
                    'MaxAgeInDays': 1000,  # should be ignored
                    'DeleteSourceFromS3': True
                }
            }
        })
    return BEIWE_APPLICATION_NAME
def get_python27_platform_arn():
    """ gets the most recent platform arm for a python 2.7 elastic beanstalk cluster.
    Warning! The query below returns different values in different AWS regions.
    We've tested this in us-east-1, us-east-2, us-west-1, and us-west-2 on November 1, 2017
    and confirmed that those 4 regions worked; however, this call may not work for other AWS
    regions, and it may break if Amazon changes the return values in the future. """
    eb_client = create_eb_client()
    platforms = []
    botoFilters = [{'Operator': 'contains', 'Type': 'PlatformName', 'Values': ['Python']}]
    # Note: regardless of the MaxRecords value, we're only seeing boto3 return 100 records max
    for platform in eb_client.list_platform_versions(MaxRecords=1000, Filters=botoFilters)['PlatformSummaryList']:
        if (platform.get('PlatformCategory', None) == 'Python' and
                    "Python 2.7" in platform.get('PlatformArn', []) and
                    "64bit Amazon Linux" in platform.get('PlatformArn', [])
            ):
            platforms.append(platform['PlatformArn'])

    platforms.sort()

    if len(platforms) == 0:
        raise PythonPlatformDiscoveryError("could not find python 2.7 platform")
    if len(platforms) > 1:
        log.error("\n***********************************************************\n"
                  "Warning: encountered multiple Python 2.7 Elastic Beanstalk environment platforms.\n"
                  "Beiwe did its best to automatically determine which environment to use.\n"
                  "After deployment finishes, determine whether there is a platform upgrade you can\n"
                  "apply for this cluster.\n"
                  "***********************************************************")
        return platforms[-1]
    if len(platforms) == 1:
        return platforms[0]
Exemple #3
0
def get_python36_platform_arn():
    """ Gets the most recent platform arn for a python 3.6 elastic beanstalk cluster, is region specific.."""
    eb_client = create_eb_client()
    platforms = []
    botoFilters = [{'Operator': 'contains', 'Type': 'PlatformName', 'Values': ['Python']}]
    # Note: regardless of the MaxRecords value, we're only seeing boto3 return 100 records max
    for platform in eb_client.list_platform_versions(MaxRecords=1000, Filters=botoFilters)['PlatformSummaryList']:
        if (platform.get(
                'PlatformCategory', None) == 'Python' and
                "Python 3.6" in platform.get('PlatformArn', []) and
                "64bit Amazon Linux" in platform.get('PlatformArn', [])
        ):
            platforms.append(platform['PlatformArn'])

    # platform arns are not necessarily human-alphanumerically, but a best effort here is fine.
    # looks like this:
    # ['arn:aws:elasticbeanstalk:us-east-1::platform/Python 3.6 running on 64bit'Amazon Linux/2.9.2',
    #  'arn:aws:elasticbeanstalk:us-east-1::platform/Python 3.6 running on 64bit Amazon Linux/2.9.3']
    platforms.sort()

    if len(platforms) == 0:
        raise PythonPlatformDiscoveryError("could not find python 3.6 platform")
    if len(platforms) > 1:
        log.error("\n***********************************************************\n"
                  "Warning: encountered multiple Python 3.6 Elastic Beanstalk environment platforms.\n"
                  "Beiwe did its best to automatically determine which environment to use.\n"
                  "After deployment finishes, determine whether there is a platform upgrade you can\n"
                  "apply for this cluster.\n"
                  "***********************************************************")
        return platforms[-1]
    if len(platforms) == 1:
        return platforms[0]
Exemple #4
0
def fix_deploy(eb_environment_name):
    # {
    #     'ResourceName': 'string',
    #     'Namespace': 'string',
    #     'OptionName': 'string',
    #     'Value': 'string'
    # },
    eb_client = create_eb_client()
    return eb_client.update_environment(
        # ApplicationName='string',
        # EnvironmentId='string',
        EnvironmentName=eb_environment_name,
        # GroupName='string',
        # Description='string',
        # Tier={
        #     'Name': 'string',
        #     'Type': 'string',
        #     'Version': 'string'
        # # },
        # VersionLabel='string',
        # TemplateName='string',
        # SolutionStackName='string',
        # PlatformArn='string',
        OptionSettings=[
            {
                'Namespace': 'aws:elasticbeanstalk:command',
                'OptionName': 'IgnoreHealthCheck',
                'Value': 'true'
            },
        ],
        # OptionsToRemove=[
        #     {
        #         'ResourceName': 'string',
        #         'Namespace': 'string',
        #         'OptionName': 'string'
        #     },
        # ]
    )
Exemple #5
0
def create_eb_environment(eb_environment_name, without_db=False):
    # Don't actually use the without_db flag in production, it is for debugging
    app = get_or_create_eb_application()

    # if not without_db:
    #     try:
    #         _ = get_db_info(eb_environment_name)
    #     except DBInstanceNotFound:
    #         log.error("could not find a database named '%s,' you must create a database first."
    #                   % construct_db_name(eb_environment_name))
    #         EXIT()

    option_settings = construct_eb_environment_variables(eb_environment_name)

    log.info(
        "creating a new Elastic Beanstalk environment named %s... this will take a while."
        % eb_environment_name)
    eb_client = create_eb_client()

    env = eb_client.create_environment(
        ApplicationName=BEIWE_APPLICATION_NAME,
        EnvironmentName=eb_environment_name,
        Description='elastic beanstalk beiwe cluster',
        PlatformArn=get_python36_platform_arn(),
        OptionSettings=option_settings,
        # VersionLabel='string',  # TODO: this will probably be required later?

        # a different form of configuration management
        # OptionsToRemove=[
        #     {'ResourceName': 'string',
        #      'Namespace': 'string',
        #      'OptionName': 'string'}]

        # Tags=[{'Key': 'string',
        #        'Value': 'string'}],

        # CNAMEPrefix='string',  # not required
        # Tier={'Name': 'string',
        #       'Type': 'string',
        #       'Version': 'string'},

        # GroupName='string',  # for use in other methods of eb configuration
        # TemplateName='string',  # nope
        # SolutionStackName='string', # more about templates
    )

    env_id = env['EnvironmentId']
    good_eb_environment_states = ["Launching", "Updating"]
    bad_eb_environment_states = ["Terminating", "Terminated"]

    while True:
        envs = retry(eb_client.describe_environments,
                     EnvironmentIds=[env_id])['Environments']
        log.info(
            '%s: Elastic Beanstalk status is "%s", waiting until status is "Ready"'
            % (current_time_string(), env['Status']))
        if len(envs) != 1:
            raise Exception(
                "describe_environments is broken, %s environments returned" %
                len(envs))
        env = envs[0]
        if env['Status'] in bad_eb_environment_states:
            msg = "environment deployment failed:\n%s" % format(env)
            log.error(
                msg
            )  # python logging is weird and this fails to print if python exits too quickly.
            raise EnvironmentDeploymentFailure(msg)
        if env['Status'] in good_eb_environment_states:
            sleep(5)
            continue
        if env['Status'] == "Ready":
            log.info("environment %s, is ready to have Beiwe deployed to it." %
                     eb_environment_name)
            break

    encrypt_eb_s3_bucket()
    allow_eb_environment_database_access(eb_environment_name)
    allow_443_traffic_to_load_balancer(eb_environment_name)
    return env
Exemple #6
0
def get_environment(eb_environment_name):
    eb_client = create_eb_client()
    return eb_client.describe_configuration_settings(
        ApplicationName="beiwe-application",
        EnvironmentName=eb_environment_name)['ConfigurationSettings'][0]
Exemple #7
0
def get_environments_list():
    environments = create_eb_client().describe_environments()['Environments']
    return [environment['EnvironmentName'] for environment in environments]