# coding: utf-8 # OceanBase Deploy. # Copyright (C) 2021 OceanBase # # This file is part of OceanBase Deploy. # # OceanBase Deploy is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # OceanBase Deploy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with OceanBase Deploy. If not, see . from __future__ import absolute_import, division, print_function from tool import ConfigUtil class CommandVariables(dict): def __getitem__(self, item): if item not in self.items(): return item else: return super(CommandVariables, self).__getitem__(item) def load_variables_from_config(variables, component, config, command_variables, stdio=None): for variable in variables: if component not in ConfigUtil.get_list_from_dict(variable, 'components', str): continue variable_name = ConfigUtil.get_value_from_dict(variable, 'name', transform_func=str) config_key = ConfigUtil.get_value_from_dict(variable, 'config_key', transform_func=str) value = config.get(config_key) if value is not None: command_variables[variable_name] = str(value) if stdio: stdio.verbose('get variable %s for config key %s, value is %s' % (variable_name, config_key, value)) def prepare_variables(plugin_context, name, context, component, server, *args, **kwargs): def get_value_from_context(key, default=None): value = context.get(key, default) stdio.verbose('get value from context: %s value %s' % (key, value)) return value cluster_config = plugin_context.cluster_config stdio = plugin_context.stdio clients = plugin_context.clients components = get_value_from_context("components", []) servers = get_value_from_context("servers", []) cmd_conf = get_value_from_context("command_config") loading_env = {} if server is None: server = cluster_config.servers[0] # find command template command_template = None interactive = None wrapper_name = None no_exception = False no_interruption = False executor = None command_variables = CommandVariables() for command in cmd_conf.all_commands: cmd_name = ConfigUtil.get_value_from_dict(command, 'name', transform_func=str) allow_components = ConfigUtil.get_list_from_dict(command, 'components', str) if component in allow_components: current_command = ConfigUtil.get_value_from_dict(command, 'command', transform_func=str) loading_env[cmd_name] = current_command if name == cmd_name: command_template = current_command interactive = ConfigUtil.get_value_from_dict(command, 'interactive', transform_func=bool) wrapper_name = ConfigUtil.get_value_from_dict(command, 'wrapper', transform_func=str) no_exception = ConfigUtil.get_value_from_dict(command, 'no_exception', transform_func=bool) no_interruption = ConfigUtil.get_value_from_dict(command, 'no_interruption', transform_func=bool) if command_template is None: stdio.error( 'There is no command {} in component {}. Please use --components to set the right component.'.format(name, component)) return if interactive and (len(components) > 1 or len(servers) > 1): stdio.error('Interactive commands do not support specifying multiple components or servers.') return cmd_input = None if server not in cluster_config.servers: if interactive: stdio.error("{} is not a server in {}".format(server, component)) return plugin_context.return_false() else: stdio.verbose("{} is not a server in {}".format(server, component)) return plugin_context.return_true(skip=True) global_config = cluster_config.get_global_conf() server_config = cluster_config.get_server_conf(server) client = clients[server] ssh_config = vars(client.config) # load global config stdio.verbose('load variables from global config') load_variables_from_config(cmd_conf.global_variables, component, global_config, command_variables, stdio) # load server config stdio.verbose('load variables from server config') load_variables_from_config(cmd_conf.server_variables, component, server_config, command_variables, stdio) # load ssh config stdio.verbose('load variables from ssh config') load_variables_from_config(cmd_conf.ssh_variables, component, ssh_config, command_variables, stdio) if wrapper_name: for wrapper in cmd_conf.all_wrappers: if wrapper_name == ConfigUtil.get_value_from_dict(wrapper, 'name', transform_func=str): local_command = ConfigUtil.get_value_from_dict(wrapper, "local_command", transform_func=str) remote_command = ConfigUtil.get_value_from_dict(wrapper, "remote_command", transform_func=str) command = ConfigUtil.get_value_from_dict(wrapper, "command", transform_func=str) cmd_input = ConfigUtil.get_value_from_dict(wrapper, "input", transform_func=str) executor = ConfigUtil.get_value_from_dict(wrapper, "executor", transform_func=str) if local_command and remote_command: if client.is_localhost(): command = local_command else: command = remote_command command_template = command.format(cmd=command_template, **command_variables) if cmd_input: cmd_input = cmd_input.format(cmd=command_template, **command_variables) break else: stdio.error("Wrapper {} not found in component {}.".format(wrapper_name, component)) for key, value in loading_env.items(): loading_env[key] = str(value).format(**command_variables) context.update( command_variables=command_variables, command_config=cmd_conf, command_template=command_template, interactive=interactive, cmd_input=cmd_input, no_exception=no_exception, no_interruption=no_interruption, component=component, server=server, env=loading_env, executor=executor) return plugin_context.return_true()