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,
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)