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")
    response = ecs.register_task_definition(file=args.task_definition_file)
    task_definition_arn = response.get('taskDefinition').get('taskDefinitionArn')
    success("Registering task definition '%s' succeeded" % task_definition_arn)

    # Step 5: Downscale ECS Service if necessary
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
    h1("Step: Register New Task Definition")
    response = ecs.register_task_definition(family=args.task_definition_name,
Beispiel #3
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)