ebcli/operations/platformops.py (285 lines of code) (raw):
# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import os
import re
import sys
from datetime import datetime
from shutil import copyfile, move
from semantic_version import Version
from ebcli.core.ebglobals import Constants
from ebcli.core import io, fileoperations
from ebcli.lib import elasticbeanstalk, heuristics, s3, utils
from ebcli.objects.exceptions import (
InvalidPlatformVersionError,
NotFoundError,
PlatformWorkspaceEmptyError,
ValidationError
)
from ebcli.objects.platform import PlatformVersion, PlatformBranch
from ebcli.operations import (
logsops,
commonops,
platform_branch_ops,
platform_version_ops,
solution_stack_ops,
)
from ebcli.operations.commonops import _zip_up_project, get_app_version_s3_location
from ebcli.operations.eventsops import print_events
from ebcli.operations.tagops import tagops
from ebcli.resources.statics import (
namespaces,
option_names,
platform_branch_lifecycle_states,
)
from ebcli.resources.regex import PlatformRegExpressions
from ebcli.resources.strings import strings, alerts, prompts
def detect_platform_family(families_set):
detected_platform_family = heuristics.find_platform_family()
if detected_platform_family and detected_platform_family in families_set:
io.echo()
io.echo(prompts['platform.validate'].format(
platform=detected_platform_family))
correct = io.get_boolean_response()
if correct:
return detected_platform_family
def get_custom_platform_from_customer(custom_platforms):
selected_platform_name = prompt_customer_for_custom_platform_name(custom_platforms)
return resolve_custom_platform_version(custom_platforms, selected_platform_name)
def get_environment_platform(app_name, env_name, want_solution_stack=False):
env = elasticbeanstalk.get_environment(
app_name=app_name,
env_name=env_name,
want_solution_stack=want_solution_stack
)
return env.platform
def get_platform_name_and_version_interactive():
platforms = platform_version_ops.get_platforms(
owner=Constants.OWNED_BY_SELF, platform_version="latest")
platform_list = list(platforms)
file_name = fileoperations.get_current_directory_name()
new_platform = False
version = None
if len(platform_list) > 0:
io.echo()
io.echo('Select a platform to use')
new_platform_option = '[ Create new Platform ]'
platform_list.append(new_platform_option)
try:
default_option = platform_list.index(file_name) + 1
except ValueError:
default_option = len(platform_list)
platform_name = utils.prompt_for_item_in_list(platform_list, default=default_option)
if platform_name == new_platform_option:
new_platform = True
else:
version = platforms[platform_name]
if len(platform_list) == 0 or new_platform:
io.echo()
io.echo('Enter Platform Name')
unique_name = utils.get_unique_name(file_name, platform_list)
platform_name = io.prompt_for_unique_name(unique_name, platform_list)
return platform_name, version
def get_version_status(version):
platform_name = fileoperations.get_platform_name()
if version is None:
version = fileoperations.get_platform_version()
if version is None:
version = platform_version_ops.get_latest_platform_version(platform_name)
fileoperations.update_platform_version(version)
if version is None:
raise InvalidPlatformVersionError(strings['exit.nosuchplatformversion'])
arn = platform_version_ops.version_to_arn(version)
_, platform_name, platform_version = PlatformVersion.arn_to_platform(arn)
platform = platform_version_ops.describe_custom_platform_version(
platform_arn=arn,
owner=Constants.OWNED_BY_SELF,
platform_name=platform_name,
platform_version=platform_version,
)
if not platform:
raise InvalidPlatformVersionError(strings['exit.nosuchplatformversion'])
created = platform.get('DateCreated')
description = platform.get('Description')
maintainer = platform.get('Maintainer')
status = platform.get('PlatformStatus')
updated = platform.get('DateUpdated')
framework_name = platform.get('FrameworkName')
framework_version = platform.get('FrameworkVersion')
os_name = platform.get('OperatingSystemName')
os_version = platform.get('OperatingSystemVersion')
language_name = platform.get('ProgrammingLanguageName')
language_version = platform.get('ProgrammingLanguageVersion')
supported_tiers = platform.get('SupportedTierList')
io.echo('Platform: ', arn)
io.echo('Name: ', platform_name)
io.echo('Version: ', version)
io.echo('Maintainer: ', maintainer) if maintainer else None
io.echo('Description: ', description) if description else None
io.echo('Framework: ', framework_name) if framework_name else None
io.echo('Framework: ', framework_name) if framework_name else None
io.echo('Framework Version: ', framework_version) if framework_version else None
io.echo('Operating System: ', os_name) if os_name else None
io.echo('Operating System Version: ', os_version) if os_version else None
io.echo('Programming Language: ', language_name) if language_name else None
io.echo('Programming Language Version: ', language_version) if language_version else None
io.echo('Supported Tiers: ', supported_tiers) if supported_tiers else None
io.echo('Status: ', status)
io.echo('Created: ', created)
io.echo('Updated: ', updated)
def generate_version_to_arn_mappings(custom_platforms, specified_platform_name):
version_to_arn_mappings = {}
for custom_platform in custom_platforms:
custom_platform_name = PlatformVersion.get_platform_name(custom_platform)
if custom_platform_name == specified_platform_name:
version_to_arn_mappings[PlatformVersion.get_platform_version(custom_platform)] = custom_platform
return version_to_arn_mappings
def get_configured_default_platform():
return commonops.get_config_setting_from_branch_or_default('default_platform')
def get_platform_for_platform_string(platform_string):
if PlatformVersion.is_valid_arn(platform_string):
return PlatformVersion(platform_string).hydrate(
elasticbeanstalk.describe_platform_version)
if platform_branch_ops.is_platform_branch_name(platform_string):
return platform_version_ops.get_preferred_platform_version_for_branch(platform_string)
return solution_stack_ops.find_solution_stack_from_string(platform_string)
def group_custom_platforms_by_platform_name(custom_platforms):
return sorted(
set(
[
PlatformVersion.get_platform_name(custom_platform)
for custom_platform in custom_platforms
]
)
)
def list_nonretired_platform_families():
"""
Provides a list of all platform branches that contain
branches that are not retired.
"""
branches = platform_branch_ops.list_nonretired_platform_branches()
families = platform_branch_ops.collect_families_from_branches(branches)
return families
def prompt_customer_for_custom_platform_name(custom_platforms):
custom_platform_names_to_display = group_custom_platforms_by_platform_name(custom_platforms)
return utils.prompt_for_item_in_list(custom_platform_names_to_display)
def prompt_customer_for_custom_platform_version(version_to_arn_mappings):
custom_platform_versions_to_display = sorted(version_to_arn_mappings.keys())
io.echo()
io.echo(prompts['sstack.version'])
chosen_custom_platform_version = utils.prompt_for_item_in_list(custom_platform_versions_to_display)
return version_to_arn_mappings[chosen_custom_platform_version]
def prompt_for_platform_family(include_custom=False):
families = list_nonretired_platform_families()
families.sort()
detected_platform_family = detect_platform_family(families)
if detected_platform_family:
return detected_platform_family
if include_custom:
families.append(prompts['platformfamily.prompt.customplatform'])
io.echo(prompts['platformfamily.prompt'])
return utils.prompt_for_item_in_list(families, default=None)
def prompt_for_platform_branch(family):
branches = platform_branch_ops.list_nonretired_platform_branches()
branches = [branch for branch in branches if branch['PlatformName'] == family]
branches = _sort_platform_branches_for_prompt(branches)
if len(branches) == 1:
return PlatformBranch.from_platform_branch_summary(branches[0])
branch_display_names = [_generate_platform_branch_prompt_text(branch) for branch in branches]
default = utils.index_of(
branches,
value=platform_branch_lifecycle_states.SUPPORTED,
key=lambda b: b['LifecycleState'])
if default == -1:
default = None
else:
default += 1
io.echo(prompts['platformbranch.prompt'])
index = utils.prompt_for_index_in_list(branch_display_names, default=default)
return PlatformBranch.from_platform_branch_summary(branches[index])
def prompt_for_platform():
custom_platform_versions = platform_version_ops.list_custom_platform_versions()
enable_custom_platform_prompt = not not custom_platform_versions
platform_family = prompt_for_platform_family(include_custom=enable_custom_platform_prompt)
if platform_family == prompts['platformfamily.prompt.customplatform']:
return get_custom_platform_from_customer(custom_platform_versions)
return prompt_for_platform_branch(platform_family)
def resolve_custom_platform_version(
custom_platforms,
selected_platform_name
):
version_to_arn_mappings = generate_version_to_arn_mappings(
custom_platforms,
selected_platform_name
)
custom_platform_versions = []
for custom_platform_version in version_to_arn_mappings.keys():
custom_platform_versions.append(Version(custom_platform_version))
if len(custom_platform_versions) > 1:
chosen_custom_platform_arn = prompt_customer_for_custom_platform_version(
version_to_arn_mappings
)
else:
chosen_custom_platform_arn = custom_platforms[0]
return PlatformVersion(chosen_custom_platform_arn)
def set_platform(platform_name, platform_version=None, verify=True):
if verify:
arn = _name_to_arn(platform_name)
_, platform_name, platform_version = PlatformVersion.arn_to_platform(arn)
fileoperations.update_platform_name(platform_name)
fileoperations.update_platform_version(platform_version)
io.echo(strings['platformset.version'])
try:
get_version_status(platform_version)
except InvalidPlatformVersionError:
io.echo(strings['platformset.newplatform'] % platform_name)
def set_workspace_to_latest():
platform_name = fileoperations.get_platform_name()
version = platform_version_ops.get_latest_platform_version(platform_name, owner=Constants.OWNED_BY_SELF)
fileoperations.update_platform_version(version)
if version is not None:
io.echo(strings['platformset.version'])
get_version_status(version)
def show_platform_events(follow, version):
platform_name = fileoperations.get_platform_name()
if version is None:
version = fileoperations.get_platform_version()
if version is None:
raise InvalidPlatformVersionError(strings['exit.nosuchplatformversion'])
platform = platform_version_ops.describe_custom_platform_version(
platform_name=platform_name,
platform_version=version,
owner=Constants.OWNED_BY_SELF
)
if platform is None:
raise InvalidPlatformVersionError(strings['exit.nosuchplatformversion'])
arn = platform['PlatformArn']
else:
arn = platform_version_ops.version_to_arn(version)
print_events(follow=follow, platform_arn=arn, app_name=None, env_name=None)
def _generate_platform_branch_prompt_text(branch):
name = branch['BranchName']
lifecycle_state = branch['LifecycleState']
if lifecycle_state == platform_branch_lifecycle_states.SUPPORTED:
return name
return '{} ({})'.format(branch['BranchName'], branch['LifecycleState'])
def _name_to_arn(platform_name):
arn = None
if PlatformRegExpressions.VALID_PLATFORM_NAME_FORMAT.match(platform_name):
arn = platform_version_ops.get_platform_arn(platform_name, "latest", owner=Constants.OWNED_BY_SELF)
elif PlatformVersion.is_valid_arn(platform_name):
arn = platform_name
elif PlatformRegExpressions.VALID_PLATFORM_SHORT_FORMAT.match(platform_name):
match = PlatformRegExpressions.VALID_PLATFORM_SHORT_FORMAT.match(platform_name)
platform_name, platform_version = match.group(1, 2)
arn = platform_version_ops.get_platform_arn(platform_name, platform_version, owner=Constants.OWNED_BY_SELF)
if not arn:
raise InvalidPlatformVersionError(strings['exit.nosuchplatform'])
return arn
def _sort_platform_branches_for_prompt(branches):
lifecycle_sort_values = {
platform_branch_lifecycle_states.SUPPORTED: 3,
platform_branch_lifecycle_states.BETA: 2,
platform_branch_lifecycle_states.DEPRECATED: 1,
}
return sorted(
branches,
key=lambda b: (
lifecycle_sort_values.get(b['LifecycleState'], 0),
float(b['BranchOrder'] or 'inf')
),
reverse=True,
)