Exemple #1
0
    def __init__(self, args):
        self.service_list = []

        task_definition_config_json = render.load_json(args.task_definition_config_json)
        files = os.listdir(args.task_definition_template_dir)
        for file in files:
            try:
                task_definitions = render.render_definition(args.task_definition_template_dir, file, task_definition_config_json, args.task_definition_config_env)
                self.service_list.extend(self.import_service_from_task_definitions(task_definitions))
            except:
                error("Template error. file: %s.\n%s" % (file, traceback.format_exc()))
                sys.exit(1)
        if args.deploy_service_group:
            self.deploy_service_list = list(filter(lambda service:service.task_environment.service_group == args.deploy_service_group, self.service_list))
        else:
            self.deploy_service_list = self.service_list
        if len(self.deploy_service_list) == 0:
            error("Deployment target service is None.")
            sys.exit(1)
        self.ecs_service = ECSService(access_key=args.key, secret_key=args.secret, region=args.region)
        self.is_service_zero_keep = args.service_zero_keep
        self.environment = task_definition_config_json['environment']
        self.template_group = args.template_group

        self.cluster_list = []
        for service in self.service_list:
            if service.task_environment.cluster_name not in self.cluster_list:
                self.cluster_list.append(service.task_environment.cluster_name)

        self.error = False
 def __init__(self, webhook_url, regions, message, tag_key, tag_value,
              lifetime_tag_key, behavior_type):
     self.logger = logging.getLogger()
     self.logger.setLevel(logging.INFO)
     self.regions = regions
     self.behavior_type = behavior_type
     self.slack_service = slack.Slack.get_instance(webhook_url, message,
                                                   tag_key, tag_value,
                                                   lifetime_tag_key)
     self.ec2_service = EC2Service(tag_key, tag_value, lifetime_tag_key,
                                   behavior_type, self.logger)
     self.rds_service = RDSService(tag_key, tag_value, lifetime_tag_key,
                                   behavior_type, self.logger)
     self.ecs_service = ECSService(tag_key, tag_value, lifetime_tag_key,
                                   behavior_type, self.logger)
class AWSTerminator:
    def __init__(self, webhook_url, regions, message, tag_key, tag_value,
                 lifetime_tag_key, behavior_type):
        self.logger = logging.getLogger()
        self.logger.setLevel(logging.INFO)
        self.regions = regions
        self.behavior_type = behavior_type
        self.slack_service = slack.Slack.get_instance(webhook_url, message,
                                                      tag_key, tag_value,
                                                      lifetime_tag_key)
        self.ec2_service = EC2Service(tag_key, tag_value, lifetime_tag_key,
                                      behavior_type, self.logger)
        self.rds_service = RDSService(tag_key, tag_value, lifetime_tag_key,
                                      behavior_type, self.logger)
        self.ecs_service = ECSService(tag_key, tag_value, lifetime_tag_key,
                                      behavior_type, self.logger)

    def process(self):
        self.logger.info('Processing AWSTerminator...')
        for region in self.regions:
            self.logger.info('Processing AWSTerminator for %s...', region)
            self.slack_service.intro_text(region)

            # Boto3 setup by region
            self.ec2_service.set_boto3(region)
            self.rds_service.set_boto3(region)
            self.ecs_service.set_boto3(region)

            # Loop on services resources
            self.ec2_service.resources_loop(region)
            self.rds_service.resources_loop(region)
            self.ecs_service.resources_loop(region)

            # Process behavior
            self.slack_service.outro_text()
            self.behavior()
            self.slack_service.clean_blocks()
            self.logger.info('Process Done for %s.\n', region)

    def behavior(self):
        self.logger.info('Processing behavior %s...', self.behavior_type)
        if self.behavior_type == 'notify':
            self.slack_service.request()
        elif self.behavior_type == 'stop':
            self.ec2_service.stop_untagged_resources()
            self.rds_service.stop_untagged_resources()
            self.ecs_service.stop_untagged_resources()
            self.slack_service.request()
        elif self.behavior_type == 'terminate':
            self.ec2_service.terminate_untagged_resources()
            self.rds_service.terminate_untagged_resources()
            self.ecs_service.terminate_untagged_resources()
            self.slack_service.request()
        else:
            self.logger.info('%s behavior does not exist.', self.behavior_type)
parser.add_argument('--service-name', dest='service_name', required=False)
parser.add_argument('--minimum-running-tasks',
                    type=int,
                    dest='minimum_running_tasks',
                    default=1,
                    required=False)
args = parser.parse_args()

try:

    serviceMode = args.service_name is not None

    # Step: Configuring AWS
    h1("Step: Configuring AWS")
    ecs = ECSService(access_key=args.key,
                     secret_key=args.secret,
                     region=args.region)
    success("Configuring AWS succeeded")

    # Step: Check ECS cluster
    h1("Step: Check ECS cluster")
    ecs.describe_cluster(cluster=args.cluster_name)
    success("Checking cluster '%s' succeeded" % args.cluster_name)

    # Step: Check ECS Service
    if serviceMode:
        h1("Step: Check ECS Service")
        response = ecs.describe_service(cluster=args.cluster_name,
                                        service=args.service_name)
        original_running_count = (
            response.get('services')[0]).get('runningCount')
# Arguments parsing
parser = argparse.ArgumentParser(description='Deploy Service on ECS')
parser.add_argument('--key', dest='key', required=True)
parser.add_argument('--secret', dest='secret', required=True)
parser.add_argument('--region', dest='region', default='us-east-1')
parser.add_argument('--cluster-name', dest='cluster_name', required=True)
parser.add_argument('--service-name', dest='service_name', required=True)
parser.add_argument('--task-definition-file', dest='task_definition_file', required=True)
parser.add_argument('--minimum-running-tasks', type=int, dest='minimum_running_tasks', default=1, required=True)
args = parser.parse_args()

try:
    # Step 1: Configuring AWS
    h1("Step 1: Configuring AWS")
    ecs = ECSService(access_key=args.key, secret_key=args.secret, region=args.region)
    success("Configuring AWS succeeded")

    # Step 2: Check ECS cluster
    h1("Step 2: Check ECS cluster")
    ecs.describe_cluster(cluster=args.cluster_name)
    success("Checking cluster '%s' succeeded" % args.cluster_name)

    # Step 3: Check ECS Service
    h1("Step 3: Check ECS Service")
    response = ecs.describe_service(cluster=args.cluster_name, service=args.service_name)
    original_running_count = (response.get('services')[0]).get('runningCount')
    success("Checking service '%s' succeeded (%d tasks running)" % (args.service_name, original_running_count))

    # Step 4: Register New Task Definition
    h1("Step 4: Register New Task Definition")
Exemple #6
0
 def __init__(self, key, secret, region):
     super().__init__()
     self.ecs_service = ECSService(access_key=key, secret_key=secret, region=region)
Exemple #7
0
class AwsProcess(Thread):
    def __init__(self, key, secret, region):
        super().__init__()
        self.ecs_service = ECSService(access_key=key, secret_key=secret, region=region)

    def run(self):
        while True:
            try:
                service, mode = task_queue.get_nowait()
            except Empty:
                time.sleep(1)
                continue
            try:
                self.process(service, mode)
            except:
                service.status = ProcessStatus.error
                error("Unexpected error. service: %s.\n%s" % (service.service_name, traceback.format_exc()))
            finally:
                task_queue.task_done()

    def process(self, service, mode):
        if service.status == ProcessStatus.error:
            error("service '%s' previous process error. skipping." % service.service_name)
            return

        if mode == ProcessMode.registerTask:
            response = self.ecs_service.register_task_definition(task_definition=service.task_definition)
            service.task_definition_arn = response.get('taskDefinition').get('taskDefinitionArn')
            success("Registering task definition '%s' succeeded (arn: '%s')" % (service.task_name, service.task_definition_arn))
            # for register task rate limit
            time.sleep(3)

        elif mode == ProcessMode.checkService:
            try:
                response = self.ecs_service.describe_service(service.task_environment.cluster_name, service.service_name)
            except ServiceNotFoundException:
                error("Service '%s' not Found." % (service.service_name))
                return
            if response['services'][0]['status'] == 'INACTIVE':
                error("Service '%s' status is INACTIVE." % (service.service_name))
                return
            service.original_task_definition = (response.get('services')[0]).get('taskDefinition')
            service.original_running_count = (response.get('services')[0]).get('runningCount')
            service.original_desired_count = (response.get('services')[0]).get('desiredCount')
            service.desired_count = service.original_desired_count
            service.service_exists = True
            success("Checking service '%s' succeeded (%d tasks running)" % (service.service_name, service.original_running_count))

        elif mode == ProcessMode.createService:
            response = self.ecs_service.create_service(cluster=service.task_environment.cluster_name, service=service.service_name, taskDefinition=service.task_definition_arn, desiredCount=service.task_environment.desired_count, maximumPercent=service.task_environment.maximum_percent, minimumHealthyPercent=service.task_environment.minimum_healthy_percent)
            service.original_running_count = (response.get('services')[0]).get('runningCount')
            service.original_desired_count = (response.get('services')[0]).get('desiredCount')
            service.desired_count = service.original_desired_count
            success("Create service '%s' succeeded (%d tasks running)" % (service.service_name, service.original_running_count))

        elif mode == ProcessMode.updateService:
            response = self.ecs_service.update_service(cluster=service.task_environment.cluster_name, service=service.service_name, taskDefinition=service.task_definition_arn, maximumPercent=service.task_environment.maximum_percent, minimumHealthyPercent=service.task_environment.minimum_healthy_percent, desiredCount=service.task_environment.desired_count)
            service.running_count = response.get('services')[0].get('runningCount')
            service.desired_count = response.get('services')[0].get('desiredCount')
            success("Update service '%s' with task definition '%s' succeeded" % (service.service_name, service.task_definition_arn))

        elif mode == ProcessMode.waitForStable:
            retryCount = 0
            while True:
                try:
                    response = self.ecs_service.wait_for_stable(cluster=service.task_environment.cluster_name, service=service.service_name)
                except WaiterError:
                    if retryCount > 2:
                        break
                    retryCount = retryCount + 1
                    continue
                break
            service.running_count = response.get('services')[0].get('runningCount')
            service.desired_count = response.get('services')[0].get('desiredCount')
            self.ecs_service.deregister_task_definition(service.original_task_definition)
            success("service '%s' (%d tasks) update completed"
                        % (service.service_name, service.running_count))
Exemple #8
0
class ServiceManager(object):
    def __init__(self, args):
        self.service_list = []

        task_definition_config_json = render.load_json(args.task_definition_config_json)
        files = os.listdir(args.task_definition_template_dir)
        for file in files:
            try:
                task_definitions = render.render_definition(args.task_definition_template_dir, file, task_definition_config_json, args.task_definition_config_env)
                self.service_list.extend(self.import_service_from_task_definitions(task_definitions))
            except:
                error("Template error. file: %s.\n%s" % (file, traceback.format_exc()))
                sys.exit(1)
        if args.deploy_service_group:
            self.deploy_service_list = list(filter(lambda service:service.task_environment.service_group == args.deploy_service_group, self.service_list))
        else:
            self.deploy_service_list = self.service_list
        if len(self.deploy_service_list) == 0:
            error("Deployment target service is None.")
            sys.exit(1)
        self.ecs_service = ECSService(access_key=args.key, secret_key=args.secret, region=args.region)
        self.is_service_zero_keep = args.service_zero_keep
        self.environment = task_definition_config_json['environment']
        self.template_group = args.template_group

        self.cluster_list = []
        for service in self.service_list:
            if service.task_environment.cluster_name not in self.cluster_list:
                self.cluster_list.append(service.task_environment.cluster_name)

        self.error = False

    def delete_unused_services(self, is_delete_unused_service):
        h1("Step: Delete Unused Service")
        if not is_delete_unused_service:
            info("Do not delete unused service")
            return

        cluster_services = {}
        for cluster_name in self.cluster_list:
            running_service_arn_list = self.ecs_service.list_services(cluster_name)
            response = self.ecs_service.describe_services(cluster_name, running_service_arn_list)
            failures = response.get('failures')

            # リストからサービス詳細が取れなければエラーにしてしまう
            if len(failures) > 0:
                for failure in failures:
                    error("list service failer. service: '%s', reason: '%s'" % (failure.get('arn'), failure.get('reason')))
                sys.exit(1)
            cluster_services[cluster_name] = response['services']

        task_definition_names = []
        task_dict = {}
        for cluster_name, d in cluster_services.items():
            for service_description in d:
                service_name = service_description['serviceName']

                task_definition_name = service_description['taskDefinition']
                response = self.ecs_service.describe_task_definition(task_definition_name)
                response_task_environment = response['taskDefinition']['containerDefinitions'][0]['environment']

                # 環境変数なし
                if len(response_task_environment) <= 0:
                    error("Service '%s' is environment value not found" % (service_name))
                    self.error = True
                    continue
                try:
                    task_environment = TaskEnvironment(response_task_environment)
                # 環境変数の値が足りない 
                except EnvironmentValueNotFoundException:
                    error("Service '%s' is lack of environment value" % (service_name))
                    self.error = True
                    continue

                # 同一環境のものだけ
                if task_environment.environment != self.environment:
                    continue
                # 同一テンプレートグループだけ
                if self.template_group:
                    if not task_environment.template_group:
                        error("Service '%s' is not set TEMPLATE_GROUP" % (service_name))
                        self.error = True
                        continue
                    if task_environment.template_group != self.template_group:
                        continue

                ident_service_list = [ service for service in self.service_list if service.service_name == service_name and service.task_environment.cluster_name == cluster_name ]

                if len(ident_service_list) <= 0:
                    success("Delete service '%s' for service template deleted" % (service_name))
                    self.ecs_service.delete_service(cluster_name, service_name)

    def import_service_from_task_definitions(self, task_definitions):
        service_list = []
        for task_definition in task_definitions:
            service = Service(task_definition)
            service_list.append(service)
        return service_list

    def check_ecs_cluster(self):
        h1("Step: Check ECS cluster")
        for cluster_name in self.cluster_list:
            self.ecs_service.describe_cluster(cluster=cluster_name)
            success("Checking cluster '%s' succeeded" % cluster_name)

    def register_new_task_definition(self):
        h1("Step: Register New Task Definition")
        for service in self.deploy_service_list:
            task_queue.put([service, ProcessMode.registerTask])
        task_queue.join()

    def check_service(self):
        h1("Step: Check ECS Service")
        for service in self.deploy_service_list:
            task_queue.put([service, ProcessMode.checkService])
        task_queue.join()

    def create_service(self):
        # Step: Create ECS Service if necessary
        not_exists_service_list = list(filter(lambda service:service.service_exists == False, self.deploy_service_list))
        if len(not_exists_service_list) > 0:
            h1("Step: Create ECS Service")
        for service in not_exists_service_list:
            task_queue.put([service, ProcessMode.createService])
        task_queue.join()

    def update_service(self):
        h1("Step: Update ECS Service")
        for service in self.deploy_service_list:
            if not service.service_exists:
                continue
            if self.is_service_zero_keep and service.original_desired_count == 0:
                # サービスのタスク数が0だったらそれを維持する
                info("Service '%s' is zero task service. skipping." % service.service_name)
            else:
                task_queue.put([service, ProcessMode.updateService])
        task_queue.join()

    def wait_for_stable(self):
        h1("Step: Wait for Service Status 'Stable'")
        for service in self.deploy_service_list:
            if not service.service_exists:
                continue
            else:
                task_queue.put([service, ProcessMode.waitForStable])
        task_queue.join()

    def result_check(self):
        error_service_list = list(filter(lambda service:service.status == ProcessStatus.error, self.deploy_service_list))
        # サービスでエラーが一個でもあれば失敗としておく
        if len(error_service_list) > 0:
            sys.exit(1)
        if self.error:
            sys.exit(1)
Exemple #9
0
parser.add_argument('--task-definition-file', dest='task_definition_file', required=True)
parser.add_argument('--service-name', dest='service_name', required=False)
parser.add_argument('--minimum-running-tasks', type=int, dest='minimum_running_tasks', default=1, required=False)
parser.add_argument('--launch-type', dest='launch_type', required=False)
parser.add_argument('--execution-role-arn', dest='execution_role_arn', required=False)
parser.add_argument('--cpu', dest='cpu', required=False)
parser.add_argument('--memory', dest='memory', required=False)
args = parser.parse_args()

try:

    serviceMode = args.service_name is not None

    # Step: Configuring AWS
    h1("Step: Configuring AWS")
    ecs = ECSService(access_key=args.key, secret_key=args.secret, region=args.region)
    success("Configuring AWS succeeded")

    # Step: Check ECS cluster
    h1("Step: Check ECS cluster")
    ecs.describe_cluster(cluster=args.cluster_name)
    success("Checking cluster '%s' succeeded" % args.cluster_name)

    # Step: Check ECS Service
    if serviceMode:
        h1("Step: Check ECS Service")
        response = ecs.describe_service(cluster=args.cluster_name, service=args.service_name)
        original_running_count = (response.get('services')[0]).get('runningCount')
        success("Checking service '%s' succeeded (%d tasks running)" % (args.service_name, original_running_count))

    # Step: Register New Task Definition