class Clean(Command('clean')): def exec(self): base_image = re.sub(r'\:.+$', '', settings.DEFAULT_RUNTIME_IMAGE) image_count = -1 def clean_images(): images = [] for image in self.manager.list_images(): if not image.tags or re.match(r"^{}\:[\d]+$".format(base_image), image.tags[0]): images.append(image) def remove(image): try: self.manager.delete_image(image.id) self.success("Successfully removed image: {}".format(image.tags[0])) except Exception as e: self.error("Failed to delete image {}: {}".format(image.id, e)) self.run_list(images, remove) return images while True: # Run potentially multiple times to clean dependent images count = clean_images() if count == image_count: break else: image_count = count
class Set(Command('env.set')): def exec(self): self.set_env( name = self.environment_name, **self.environment_fields )
class Version(Command('version')): def exec(self): env = self.get_env() if not settings.API_EXEC: self.table( self.render_list(self._environment, filters={'name': env.name})) self.info('') self.data("> Client version", self.get_version(), 'client_version') if env.host and env.user and env.token: result = self.exec_remote(env, 'version', display=False) self.data("> Server version", result.named['server_version'].data) self.data("> Server environment", result.named['server_env'].data) self.data("> Server runtime repository", result.named['server_repo'].data) self.data("> Server runtime image", result.named['server_image'].data) if env.name != result.named['server_env'].data: self.warning( "Local and remote environment names do not match. Use remote environment name locally to avoid sync issues." ) else: self.silent_data('server_version', self.get_version()) self.silent_data('server_env', env.name) self.silent_data('server_repo', env.repo) self.silent_data('server_image', env.base_image)
class Export(Command('export')): def exec(self): self.options.add('module_name', 'core') self.module.provider.export_profile( self.profile_components )
class Task(Command('task')): def exec(self): self.module.provider.exec_task( self.task_name, self.task_fields )
class Run(Command('run')): def exec(self): self.module.provider.run_profile(self.profile_name, config=self.profile_config_fields, components=self.profile_components, display_only=self.display_only, plan=self.plan, ignore_missing=self.ignore_missing)
class Reset(Command('module.reset')): def exec(self): env = self.get_env() self.set_state('old_runtime_image', env.runtime_image) self.save_env(runtime_image=None) self.set_state('module_ensure', True) self.success("Successfully reset module runtime")
class Pull(Command('db.pull')): def exec(self): self.silent_data('db', self.db.save(self.db_packages, encrypted = False)) def postprocess(self, response): self.db.load(response['db'], encrypted = False) self.success("Database packages {} successfully pulled".format(",".join(self.db_packages)))
class Import(Command('import')): def exec(self): Importer(self, display_only = self.show_spec).run( required_names = self.import_names, required_tags = self.tags, ignore_requirements = self.ignore_requirements )
class Push(Command('db.push')): def preprocess(self, options): options['db'] = self.db.save(self.db_packages, encrypted=False) def exec(self): self.db.load(self.options.get('db'), encrypted=False) self.success("Database packages {} successfully pushed".format( ",".join(self.db_packages)))
class Generate(Command('template.generate')): def exec(self): self.provision_template( self.module, self.module_template, self.template_fields, display_only = self.display_only )
class Abort(Command('log.abort')): def exec(self): def abort_command(log_key): self.publish_abort(log_key) self.wait_for_tasks(log_key) self.success("Task {} successfully aborted".format(log_key)) self.run_list(self.log_names, abort_command)
class Get(Command('log.get')): def exec(self): self.table( [[self.key_color("Log key"), self.value_color(self.log_name)], [self.key_color("Command"), self.value_color(self.log.command)], [self.key_color("Status"), self.log.status], [self.key_color("User"), self.log.user.name], [self.key_color("Scheduled"), self.log.scheduled], [self.key_color("Started"), self.format_time(self.log.created)], [ self.key_color("Last Updated"), self.format_time(self.log.updated) ]], 'data') parameter_table = [[ self.key_color("Parameter"), self.key_color("Value") ]] for name, value in self.log.config.items(): parameter_table.append([self.key_color(name), value]) self.table(parameter_table, 'parameters') self.info("\nCommand Messages:\n") if self.log.running(): log = self.log created = log.created while self.connected(): for record in log.messages.filter( created__gt=created).order_by('created'): self.message(self.create_message(record.data, decrypt=False), log=False) created = record.created log = self._log.retrieve(self.log_name) if not log.running(): if log.success(): self.success( "Command '{}' completed successfully".format( log.command)) else: self.warning( "Command '{}' completed with errors".format( log.command)) break self.sleep(self.poll_interval) else: for record in self.log.messages.all().order_by('created'): self.message(self.create_message(record.data, decrypt=False), log=False)
class Destroy(Command('destroy')): def exec(self): self.module.provider.destroy_profile( self.profile_name, config = self.profile_config_fields, components = self.profile_components, display_only = self.display_only, ignore_missing = self.ignore_missing )
class Logs(Command('service.logs')): def exec(self): self.disable_logging() service_names = self.service_names if self.service_names else self.manager.service_names try: self.manager.display_service_logs(service_names, tail=self.tail, follow=self.follow) except KeyboardInterrupt: sys.exit(0)
class Sync(Command('module.sync')): def exec(self): self.silent_data('modules', self.db.save('module', encrypted=False)) def postprocess(self, response): self.db.load(response['modules'], encrypted=False) for module in self.get_instances(self._module): module.provider.update() self.exec_local('module install') self.success('Modules successfully synced from remote environment')
class Stop(Command('processor.stop')): def exec(self): def stop_service(name): self.manager.stop_service(self, name, self.remove) self.success("Successfully stopped {} service".format(name)) self.run_list([ 'zimagi-scheduler', 'zimagi-worker' ], stop_service)
class Init(Command('module.init')): def bootstrap_ensure(self): return False def exec(self): def init_modules(): initialized = self.get_state('startup_initialized') if self.reset or not initialized: self.ensure_resources() self.set_state('startup_initialized', True) self.run_exclusive('module_init', init_modules, timeout=self.timeout)
class Children(Command('group.children')): def exec(self): self.exec_local('group save', { 'group_name': self.group_name, 'verbosity': 0 }) parent = self._group.retrieve(self.group_name) for group in self.group_names: self._group.store(group, provider_type=parent.provider_type, parent=parent) self.success("Successfully saved group {}".format(parent.name))
class Start(Command('processor.start')): def get_service_config(self): config = { 'ZIMAGI_LOG_LEVEL': settings.LOG_LEVEL, 'ZIMAGI_WORKER_CONCURRENCY': 2 } for name, value in dict(os.environ).items(): if name.startswith('ZIMAGI_') and name != 'ZIMAGI_CLI_EXEC': config[name] = value return config def start_dependencies(self): def start_dependency(name): self.exec_local("{} start".format(name)) self.run_list(['queue'], start_dependency) def exec(self): self.start_dependencies() def start_service(info): self.manager.start_service(self, info[0], self.environment_image, {}, docker_entrypoint=info[0], network_mode='host', environment=self.get_service_config(), volumes={ '/var/run/docker.sock': { 'bind': '/var/run/docker.sock', 'mode': 'rw' }, '/usr/local/share/zimagi': { 'bind': '/usr/local/share/zimagi', 'mode': 'ro' }, '/usr/local/lib/zimagi': { 'bind': '/usr/local/lib/zimagi', 'mode': 'rw' }, '/var/local/zimagi': { 'bind': '/var/local/zimagi', 'mode': 'rw' } }, memory=info[1], wait=20) self.success("Successfully started {} service".format(info[0])) self.run_list([('zimagi-scheduler', self.scheduler_memory), ('zimagi-worker', self.worker_memory)], start_service)
class Stop(Command('service.stop')): def exec(self): self.disable_logging() service_names = self.service_names if self.service_names else self.manager.service_names def stop_service(service_name): self.manager.stop_service(service_name) self.success("Successfully stopped service: {}".format(service_name)) self.run_list(service_names, stop_service)
class Restart(Command('service.restart')): def exec(self): self.disable_logging() service_names = self.service_names if self.service_names else self.manager.service_names def restart_service(service_name): self.manager.stop_service(service_name) self.manager.get_service(service_name) self.success( "Successfully restarted service: {}".format(service_name)) self.run_list(service_names, restart_service)
class List(Command('service.list')): def exec(self): service_map = [['Service', 'Status']] self.success('Available services:') for service_name in self.manager.service_names: data = self.manager.get_service(service_name, restart=False, create=False) service_map.append([ service_name, data['service'].status if data and 'service' in data else 'not running' ]) self.table(service_map, 'services')
class Rotate(Command('user.rotate')): def exec(self): user = self.user if self.user_name else self.active_user token = self._user.generate_token() user.set_password(token) user.save() self.silent_data('name', user.name) self.data("User {} token:".format(user.name), token, 'token') def postprocess(self, response): host = self.get_host() if host and host.user == response['name']: self.save_host(token=response['token'])
class Rerun(Command('log.rerun')): def exec(self): def rerun_command(log_key): log = self._log.retrieve(log_key) if log: options = copy.deepcopy(log.config) options['push_queue'] = True rerun_key = self.exec_local(log.command, options) self.success("Task {}:{} was successfully rerun: {}".format( log.command, log_key, rerun_key)) else: self.error("Log key {} does not exist".format(log_key)) self.run_list(self.log_names, rerun_command)
class Save(Command('notification.save')): def exec(self): command = self.notify_command instance, created = self._notification.store(command) for group in self.notify_groups: if self.notify_failure: instance.failure_groups.get_or_create(group=group) self.success( "Group {} subscribed to {} failure notifications".format( group.name, command)) else: instance.groups.get_or_create(group=group) self.success("Group {} subscribed to {} notifications".format( group.name, command))
class Destroy(Command('service.destroy')): def exec(self): self.disable_logging() service_names = self.service_names if self.service_names else self.manager.service_names def destroy_service(service_name): self.manager.stop_service(service_name, remove=True, remove_volumes=self.remove_volumes, remove_image=self.remove_image, remove_network=not self.keep_network) self.success( "Successfully destroyed service: {}".format(service_name)) self.run_list(service_names, destroy_service)
class Remove(Command('notification.remove')): def exec(self): command = self.notify_command instance, created = self._notification.store(command) for group in self.notify_groups: if self.notify_failure: instance.failure_groups.filter(group=group).delete() self.success( "Group {} unsubscribed from {} failure notifications". format(group.name, command)) else: instance.groups.filter(group=group).delete() self.success( "Group {} unsubscribed from {} notifications".format( group.name, command))
class Get(Command('service.get')): def exec(self): service_spec = self.manager.get_service_spec(self.service_name) self.data(self.key_color(self.service_name), "\n\n" + oyaml.dump(service_spec), 'service') data = self.manager.get_service(self.service_name, restart=False, create=False) if data: status = data[ 'service'].status if 'service' in data else 'not running' self.data('Status', status, 'status') ports = data['ports'] if 'ports' in data else 'none' self.data('Ports', "\n\n" + oyaml.dump(ports), 'ports')
class Add(Command('module.add')): def parse(self): super().parse() self.parse_scope(self._module) self.parse_dependency(self._module) self.parse_relations(self._module) self.parse_module_fields(True, help_callback=self.get_provider( 'module', 'help').field_help, exclude_fields=['remote']) def exec(self): self.set_scope(self._module) self.module_fields['remote'] = self.remote self.module_provider.create(None, self.module_fields)