# # All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or # its licensors. # # For complete copyright and license terms please see the LICENSE at the root of this # distribution (the "License"). All use of this software is governed by the License, # or, if provided, by the license below or the license accompanying this file. Do not # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # $Revision: #1 $ import sys import traceback from six import iteritems from six.moves import _thread from botocore.exceptions import NoCredentialsError from botocore.exceptions import EndpointConnectionError from botocore.exceptions import IncompleteReadError from botocore.exceptions import ConnectionError from botocore.exceptions import UnknownEndpointError from . import project from . import deployment from . import mappings from . import resource_group from . import profile from . import util from . import importer from . import function from . import gem from .errors import HandledError from .context import Context from .metrics import MetricsContext from .view import ViewContext from .util import Args command_handlers = { 'list-importable-resources': importer.list_aws_resources, 'import-resource': importer.import_resource, 'describe-project': project.describe, 'create-project-stack': project.create_stack, 'list-regions': project.get_regions, 'update-mappings': mappings.force_update, 'list-mappings': mappings.list, 'list-deployments': deployment.list, 'list-resource-groups': resource_group.list, 'list-project-resources': project.list_project_resources, 'list-deployment-resources': deployment.list_deployment_resources, 'list-resource-group-resources': resource_group.list_resource_group_resources, 'default-deployment': deployment.default, 'default-profile': profile.default, 'list-profiles': profile.list, 'add-profile': profile.add, 'remove-profile': profile.remove, 'update-profile': profile.update, 'rename-profile': profile.rename, 'describe-project-stack': project.describe_stack, 'describe-deployment-stack': deployment.describe_stack, 'describe-resource-group-stack': resource_group.describe_stack, 'upload-resources': deployment.upload_resources, 'upload-lambda-code': function.upload_lambda_code, 'update-project-stack': project.update_stack, 'disable-resource-group': resource_group.disable, 'enable-resource-group': resource_group.enable, 'create-deployment-stack': deployment.create_stack, 'delete-deployment-stack' : deployment.delete_stack, 'protect-deployment' : deployment.protect, 'create-function-folder': resource_group.create_function_folder, 'update-framework-version': project.update_framework_version, 'create-cloud-gem': gem.create_gem } def execute(command, args): _thread.start_new_thread(__execute, (command, args)) def __execute(command, args): requestId = args['request_id'] if 'request_id' in args else 0 print('command started - {} with args {}'.format(command, args)) metricsInterface = MetricsContext('gui') metricsInterface.set_command_name(command) metricsInterface.submit_attempt() try: argsObj = Args(**args) argsObj.no_prompt = True argsObj.is_gui = True context = Context(metricsInterface,view_class=GuiViewContext) context.bootstrap(argsObj) context.initialize(argsObj) # Deprecated in 1.9. TODO: remove. context.hooks.call_module_handlers('cli-plugin-code/resource_commands.py','add_gui_commands', args=[command_handlers, argsObj], deprecated=True ) context.hooks.call_module_handlers('cli-plugin-code/resource_commands.py', 'add_gui_view_commands', args=[context.view], deprecated=True ) context.hooks.call_module_handlers('resource-manager-code/command.py','add_gui_commands', kwargs={ 'handlers': command_handlers } ) context.hooks.call_module_handlers('resource-manager-code/command.py', 'add_gui_view_commands', kwargs={ 'view_context': context.view } ) handler = command_handlers.get(command, None) if handler is None: raise HandledError('Unknown command: ' + command) if handler != project.update_framework_version: context.config.verify_framework_version() handler(context, argsObj) context.view.success() metricsInterface.submit_success() except HandledError as e: metricsInterface.submit_failure() msg = str(e) print('command error - {} when executing command {} with args {}.'.format(msg, command, args)) args['view_output_function'](requestId, 'error', msg) except NoCredentialsError: metricsInterface.submit_failure() msg = 'No AWS credentials were provided.' print('command error - {} when executing command {} with args {}.'.format(msg, command, args)) args['view_output_function'](requestId, 'error', msg) except (EndpointConnectionError, IncompleteReadError, ConnectionError, UnknownEndpointError) as e: metricsInterface.submit_failure() msg = 'We were unable to contact your AWS endpoint.\nERROR: {0}'.format(e) print('command error - {} when executing command {} with args {}.'.format(msg, command, args)) args['view_output_function'](requestId, 'error', msg) except: metricsInterface.submit_failure() info = sys.exc_info() msg = traceback.format_exception(*info) print('command error - {} when executing command {} with args {}.'.format(msg, command, args)) args['view_output_function'](requestId, 'error', msg) print('command finished - {} with args {}'.format(command, args)) class GuiViewContext(ViewContext): def __init__(self, context): # Print calls in Python 2 when called from C++ need to be wrapped to avoid an error. # Redirect them to nowhere for now. class GuiNullWriter(object): def write(self, value): pass sys.stdout = sys.stderr = GuiNullWriter() super(GuiViewContext, self).__init__(context) def initialize(self, args): super(GuiViewContext, self).initialize(args) self.__view_output_function = args.view_output_function self.__requestId = args.request_id if args.request_id is not None else 0 def project_stack_exists(self, value): self._output('project_stack_exists', value) def _output(self, key, value): print('command output - requestId: {}, key: {}, value: {}'.format(self.__requestId, key, value)) self.__view_output_function(self.__requestId, str(key).encode('utf-8'), value) def success(self): self._output('success', 'Operation completed successfully.') def loading_file(self, path): pass # suppressed in gui def importable_resource_list(self, importable_resources): self._output('importable-resource-list', { 'ImportableResources': importable_resources }) def mapping_list(self, deployment_name, mappings, protected): self._output('mapping-list', { 'DeploymentName': deployment_name, 'Protected': protected, 'Mappings': mappings }) def deployment_updated(self, deployment_name): self._output('deployment-updated', { 'DeploymentName': deployment_name }) def confirm_writable_try_again(self, path_list): raise HandledError('Files not writable: {}'.format(path_list)) def deployment_list(self, deployments): self._output('deployment-list', { 'Deployments': deployments }) def resource_group_list(self, deployment_name, resource_groups): self._output('resource-group-list', { 'DeploymentName': deployment_name, 'ResourceGroups': resource_groups }) def project_resource_list(self, stack_id, resources_map): self.resource_list(stack_id, None, None, resources_map) def deployment_resource_list(self, stack_id, deployment_name, resources_map): self.resource_list(stack_id, deployment_name, None, resources_map) def resource_group_resource_list(self, stack_id, deployment_name, resource_group_name, resources_map): self.resource_list(stack_id, deployment_name, resource_group_name, resources_map) def resource_list(self, stack_id, deployment_name, resource_group_name, resource_map): resource_list = [] for k, v in iteritems(resource_map): v['Name'] = k resource_list.append(v) self._output('resource-list', { 'StackId': stack_id, 'DeploymentName': deployment_name, 'ResourceGroupName': resource_group_name, 'Resources': resource_list }) def profile_list(self, profiles, credentials_file_path): self._output('profile-list', { 'CredentialsFilePath': credentials_file_path, 'Profiles': profiles }) def project_description(self, description): self._output('project-description', { 'ProjectDetails': description }) def describing_stack(self, stack_id): self._output_message('Retrieving description of stack {}.'.format(util.get_stack_name_from_arn(stack_id))) def project_stack_description(self, stack_description): self._output('project-stack-description', { 'StackDescription': stack_description }) def deployment_stack_description(self, deployment_name, stack_description): self._output('deployment-stack-description', { 'DeploymentName': deployment_name, 'StackDescription': stack_description }) def resource_group_stack_description(self, deployment_name, resource_group_name, stack_description, user_defined_resource_count): self._output('resource-group-stack-description', { 'DeploymentName': deployment_name, 'ResourceGroupName': resource_group_name, 'UserDefinedResourceCount': user_defined_resource_count, 'StackDescription': stack_description }) def stack_event_errors(self, errors, was_successful): self._output('stack-event-errors', { 'Errors': errors }) def supported_region_list(self, region_list): self._output('supported-region-list', region_list)