ebcli/controllers/logs.py (134 lines of code) (raw):

# Copyright 2014 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 argparse from cement.utils.misc import minimal_logger from ebcli.core.abstractcontroller import AbstractBaseController from ebcli.objects.exceptions import InvalidOptionsError from ebcli.operations import logsops from ebcli.resources.statics import logs_operations_constants from ebcli.resources.strings import strings, flag_text LOG = minimal_logger(__name__) class LogsController(AbstractBaseController): class Meta: argument_formatter = argparse.RawTextHelpFormatter label = 'logs' description = strings['logs.info'] usage = AbstractBaseController.Meta.usage.replace('{cmd}', label) arguments = AbstractBaseController.Meta.arguments + [ (['-a', '--all'], dict( action='store_true', help=flag_text['logs.all'])), (['-z', '--zip'], dict( action='store_true', help=flag_text['logs.zip'])), (['-i', '--instance'], dict(help=flag_text['logs.instance'])), (['-g', '--log-group'], dict(help=flag_text['logs.log-group'])), (['-cw', '--cloudwatch-logs'], dict(help=flag_text['logs.cloudwatch_logs'], nargs='?', choices=['enable', 'disable'], type=str.lower, const='enable')), (['-cls', '--cloudwatch-log-source'], dict(help=flag_text['logs.cloudwatch_log_source'])), (['--stream'], dict(action='store_true', help=flag_text['logs.stream'])), ] epilog = strings['logs.epilog'] def do_command(self): self.env_name = self.get_env_name() self.app_name = self.get_app_name() self.log_group = self.app.pargs.log_group self.instance = self.app.pargs.instance self.all = self.app.pargs.all self.zip = self.app.pargs.zip self.cloudwatch_logs = self.app.pargs.cloudwatch_logs self.cloudwatch_log_source = self.app.pargs.cloudwatch_log_source self.stream = self.app.pargs.stream self.__raise_if_incompatible_arguments_are_present() if self.cloudwatch_logs: self.__modify_log_streaming() elif self.stream: self.__stream_cloudwatch_logs() else: self.__get_logs() def __get_logs(self): """ Determines whether to: - retrieve logs from CloudWatch or Beanstalk - from CloudWatch when log-streaming to CloudWatch is enabled - from Beanstalk when log-streaming to CloudWatch is disabled - retrieve instance or environment-health logs - instance logs when --cloudwatch-log-source is 'instance' or None - environment-health logs when --cloudwatch-log-source is 'environment-health' - all other values for --cloudwatch-log-source will result in an exception being thrown - determine whether to tail the logs, or to download them as a zip file or regular log files """ info_type = logsops.resolve_log_result_type(self.zip, self.all) should_zip_logs = self.zip if self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.ENVIRONMENT_HEALTH_LOG_SOURCE: logsops.raise_if_environment_health_log_streaming_is_not_enabled(self.app_name, self.env_name) logsops.retrieve_cloudwatch_environment_health_logs( self.__normalized_log_group_name(), info_type, do_zip=should_zip_logs, ) elif self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.INSTANCE_LOG_SOURCE: logsops.raise_if_instance_log_streaming_is_not_enabled(self.app_name, self.env_name) self.__retrieve_cloudwatch_instance_logs(info_type, should_zip_logs) elif self.cloudwatch_log_source: raise InvalidOptionsError(strings['logs.cloudwatch_log_source_argumnent_is_invalid_for_retrieval']) elif logsops.instance_log_streaming_enabled(self.app_name, self.env_name): self.__retrieve_cloudwatch_instance_logs(info_type, should_zip_logs) else: logsops.retrieve_beanstalk_logs( self.env_name, info_type, do_zip=should_zip_logs, instance_id=self.instance ) def __modify_log_streaming(self): self.cloudwatch_log_source = self.cloudwatch_log_source or logs_operations_constants.LOG_SOURCES.INSTANCE_LOG_SOURCE if self.cloudwatch_logs in ['enable', None]: logsops.enable_cloudwatch_logs(self.app_name, self.env_name, self.cloudwatch_log_source) elif self.cloudwatch_logs == 'disable': logsops.disable_cloudwatch_logs(self.app_name, self.env_name, self.cloudwatch_log_source) def __normalized_log_group_name(self): return logsops.normalize_log_group_name( self.env_name, self.log_group, self.cloudwatch_log_source ) def __retrieve_cloudwatch_instance_logs(self, info_type, should_zip_logs): logsops.retrieve_cloudwatch_instance_logs( self.__normalized_log_group_name(), info_type, do_zip=should_zip_logs, specific_log_stream=self.instance ) def __raise_if_incompatible_arguments_are_present(self): if self.all and self.instance: raise InvalidOptionsError(strings['logs.all_argument_and_instance_argument']) if self.all and self.zip: raise InvalidOptionsError(strings['logs.all_argument_and_zip_argument']) if self.cloudwatch_logs and self.log_group: raise InvalidOptionsError(strings['logs.cloudwatch_logs_argument_and_log_group_argument']) if self.cloudwatch_logs and self.instance: raise InvalidOptionsError(strings['logs.cloudwatch_logs_argument_and_instance_argument']) if self.cloudwatch_logs and self.all: raise InvalidOptionsError(strings['logs.cloudwatch_logs_argument_and_all_argument']) if self.cloudwatch_logs and self.zip: raise InvalidOptionsError(strings['logs.cloudwatch_logs_argument_and_zip_argument']) if self.cloudwatch_log_source and self.cloudwatch_log_source not in [ logs_operations_constants.LOG_SOURCES.ALL_LOG_SOURCES, logs_operations_constants.LOG_SOURCES.INSTANCE_LOG_SOURCE, logs_operations_constants.LOG_SOURCES.ENVIRONMENT_HEALTH_LOG_SOURCE, ]: raise InvalidOptionsError( strings['logs.cloudwatch_log_source_argumnent_is_invalid_for_enabling_streaming'] ) if ( self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.ENVIRONMENT_HEALTH_LOG_SOURCE and self.instance ): raise InvalidOptionsError(strings['logs.health_and_instance_argument']) if ( self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.ENVIRONMENT_HEALTH_LOG_SOURCE and self.log_group ): raise InvalidOptionsError(strings['logs.log_group_and_environment_health_log_source']) if self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.ALL_LOG_SOURCES and self.stream: raise InvalidOptionsError(strings['logs.cloudwatch_log_source_argumnent_is_invalid_for_enabling_streaming']) def __stream_cloudwatch_logs(self): self.cloudwatch_log_source = self.cloudwatch_log_source or logs_operations_constants.LOG_SOURCES.INSTANCE_LOG_SOURCE if self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.INSTANCE_LOG_SOURCE: if not logsops.instance_log_streaming_enabled(self.app_name, self.env_name): raise InvalidOptionsError(strings['logs.instance_log_streaming_disabled'].format(self.env_name)) logsops.stream_instance_logs_from_cloudwatch( log_group=self.__normalized_log_group_name(), specific_log_stream=self.instance ) if self.cloudwatch_log_source == logs_operations_constants.LOG_SOURCES.ENVIRONMENT_HEALTH_LOG_SOURCE: if not logsops.environment_health_streaming_enabled(self.app_name, self.env_name): raise InvalidOptionsError(strings['logs.environment_health_log_streaming_disabled'].format(self.env_name)) logsops.stream_instance_logs_from_cloudwatch(log_group=self.__normalized_log_group_name())