Path: blob/develop/awscli/customizations/ecs/executecommand.py
1567 views
# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12import logging13import json14import errno1516from subprocess import check_call17from awscli.compat import ignore_user_entered_signals18from awscli.clidriver import ServiceOperation, CLIOperationCaller1920logger = logging.getLogger(__name__)2122ERROR_MESSAGE = (23'SessionManagerPlugin is not found. ',24'Please refer to SessionManager Documentation here: ',25'http://docs.aws.amazon.com/console/systems-manager/',26'session-manager-plugin-not-found'27)2829TASK_NOT_FOUND = (30'The task provided in the request was '31'not found.'32)333435class ECSExecuteCommand(ServiceOperation):3637def create_help_command(self):38help_command = super(ECSExecuteCommand, self).create_help_command()39# change the output shape because the command provides no output.40self._operation_model.output_shape = None41return help_command424344def get_container_runtime_id(client, container_name, task_id, cluster_name):45describe_tasks_params = {46"cluster": cluster_name,47"tasks": [task_id]48}49describe_tasks_response = client.describe_tasks(**describe_tasks_params)50# need to fail here if task has failed in the intermediate time51tasks = describe_tasks_response['tasks']52if not tasks:53raise ValueError(TASK_NOT_FOUND)54response = describe_tasks_response['tasks'][0]['containers']55for container in response:56if container_name == container['name']:57return container['runtimeId']585960def build_ssm_request_paramaters(response, client):61cluster_name = response['clusterArn'].split('/')[-1]62task_id = response['taskArn'].split('/')[-1]63container_name = response['containerName']64# in order to get container run-time id65# we need to make a call to describe-tasks66container_runtime_id = \67get_container_runtime_id(client, container_name,68task_id, cluster_name)69target = "ecs:{}_{}_{}".format(cluster_name, task_id,70container_runtime_id)71ssm_request_params = {"Target": target}72return ssm_request_params737475class ExecuteCommandCaller(CLIOperationCaller):76def invoke(self, service_name, operation_name, parameters, parsed_globals):77try:78# making an execute-command call to connect to an79# active session on a container would require80# session-manager-plugin to be installed on the client machine.81# Hence, making this empty session-manager-plugin call82# before calling execute-command to ensure that83# session-manager-plugin is installed84# before execute-command-command is made85check_call(["session-manager-plugin"])86client = self._session.create_client(87service_name, region_name=parsed_globals.region,88endpoint_url=parsed_globals.endpoint_url,89verify=parsed_globals.verify_ssl)90response = client.execute_command(**parameters)91region_name = client.meta.region_name92profile_name = self._session.profile \93if self._session.profile is not None else ''94endpoint_url = client.meta.endpoint_url95ssm_request_params = build_ssm_request_paramaters(response, client)96# ignore_user_entered_signals ignores these signals97# because if signals which kills the process are not98# captured would kill the foreground process but not the99# background one. Capturing these would prevents process100# from getting killed and these signals are input to plugin101# and handling in there102with ignore_user_entered_signals():103# call executable with necessary input104check_call(["session-manager-plugin",105json.dumps(response['session']),106region_name,107"StartSession",108profile_name,109json.dumps(ssm_request_params),110endpoint_url])111return 0112except OSError as ex:113if ex.errno == errno.ENOENT:114logger.debug('SessionManagerPlugin is not present',115exc_info=True)116raise ValueError(''.join(ERROR_MESSAGE))117118119