package org.ovirt.engine.exttool.core;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.ovirt.engine.api.extensions.Base;
import org.ovirt.engine.api.extensions.ExtKey;
import org.ovirt.engine.api.extensions.ExtMap;
import org.ovirt.engine.core.extensions.mgr.ExtensionProxy;
import org.ovirt.engine.core.extensions.mgr.ExtensionsManager;
import org.ovirt.engine.core.uutils.cli.parser.ArgumentsParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InfoServiceImpl implements ModuleService {
private static final Logger log = LoggerFactory.getLogger(InfoServiceImpl.class);
private static final List<ExtKey> CONTEXT_IGNORE_KEYS = Arrays.asList(
Base.ContextKeys.GLOBAL_CONTEXT,
Base.ContextKeys.CONFIGURATION,
Base.ContextKeys.CONFIGURATION_SENSITIVE_KEYS,
ExtensionsManager.TRACE_LOG_CONTEXT_KEY
);
@FunctionalInterface
private interface Logic {
void execute(InfoServiceImpl module);
}
private enum Action {
CONFIGURATION(
module -> {
ExtensionProxy extension = module.getExtensionsManager().getExtensionByName((String)module.argMap.get("extension-name"));
Collection<?> sensitive = extension.getContext().get(Base.ContextKeys.CONFIGURATION_SENSITIVE_KEYS);
Map<Object, Object> config = extension.getContext().<Properties>get(Base.ContextKeys.CONFIGURATION);
Collection<Object> keys = new HashSet<>(config.keySet());
if (module.argMap.get("key") != null) {
keys.retainAll((List<String>)module.argMap.get("key"));
}
for (Object key : keys) {
module.output(
((String)module.argMap.get("format")).replace(
"{key}",
String.format("%s", key)
).replace(
"{value}",
sensitive.contains(key) ? "***" : String.format("%s", config.get(key))
),
" "
);
}
}
),
CONTEXT(
module -> {
ExtensionProxy extension = module.getExtensionsManager().getExtensionByName((String)module.argMap.get("extension-name"));
Collection<ExtKey> keys = new HashSet<>(extension.getContext().keySet());
if (module.argMap.get("key") != null) {
Collection<ExtKey> k = new HashSet<>();
for (String uuid : (List<String>)module.argMap.get("key")) {
k.add(new ExtKey("Unknown", Object.class, uuid));
}
keys.retainAll(k);
}
for (ExtKey key : keys) {
if (CONTEXT_IGNORE_KEYS.contains(key)) {
continue;
}
if ((key.getFlags() & ExtKey.Flags.SKIP_DUMP) != 0) {
continue;
}
module.output(
((String)module.argMap.get("format")).replace(
"{key}",
key.getUuid().getUuid().toString()
).replace(
"{name}",
key.getUuid().getName()
).replace(
"{value}",
(key.getFlags() & ExtKey.Flags.SENSITIVE) != 0 ? "***" : extension.getContext().get(key).toString()
),
" "
);
}
}
),
LIST_EXTENSIONS(
module -> {
for (ExtensionProxy extension : module.getExtensionsManager().getExtensions()) {
ExtMap extContext = extension.getContext();
module.output(
((String)module.argMap.get("format")).replace(
"{instance}",
extContext.<String>get(Base.ContextKeys.INSTANCE_NAME, "")
).replace(
"{name}",
extContext.<String>get(Base.ContextKeys.EXTENSION_NAME, "")
).replace(
"{version}",
extContext.<String>get(Base.ContextKeys.VERSION, "")
).replace(
"{license}",
extContext.<String>get(Base.ContextKeys.LICENSE, "")
).replace(
"{notes}",
extContext.<String>get(Base.ContextKeys.EXTENSION_NOTES, "")
),
""
);
}
}
);
private Logic logic;
private Action(Logic logic) {
this.logic = logic;
}
Map<String, Object> parse(Map<String, String> substitutions, Properties props, List<String> actionArgs) {
ArgumentsParser parser = new ArgumentsParser(props, actionArgs.remove(0));
parser.getSubstitutions().putAll(substitutions);
parser.parse(actionArgs);
Map<String, Object> argMap = parser.getParsedArgs();
if((Boolean)argMap.get("help")) {
System.out.format("Usage: %s", parser.getUsage());
throw new ExitException("Help", 0);
}
if(!parser.getErrors().isEmpty()) {
for(Throwable t : parser.getErrors()) {
log.error(t.getMessage());
}
throw new ExitException("Parsing error", 1);
}
if (actionArgs.size() != 0) {
log.error("Extra parameters in command-line");
throw new ExitException("Parsing error", 1);
}
return argMap;
}
void execute(InfoServiceImpl module) {
logic.execute(module);
}
}
private ExtMap context;
private Action action;
private Map<String, Object> argModuleMap;
private Map<String, Object> argMap;
private ExtensionsManager getExtensionsManager() {
return (ExtensionsManager)context.get(ContextKeys.EXTENSION_MANAGER);
}
private void output(String s, String logIndent) {
if ("log".equals(argModuleMap.get("output"))) {
log.info("{}{}", logIndent, s);
} else if ("stdout".equals(argModuleMap.get("output"))) {
System.out.println(s);
}
}
@Override
public String getName() {
return "info";
}
@Override
public String getDescription() {
return "General information.";
}
@Override
public void setContext(ExtMap context) {
this.context = context;
}
@Override
public ExtMap getContext() {
return context;
}
@Override
public void parseArguments(List<String> args) throws Exception {
args.remove(0);
Properties props = new Properties();
try (
InputStream in = InfoServiceImpl.class.getResourceAsStream("info.properties");
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)
) {
props.load(reader);
}
Map<String, String> substitutions = context.get(ContextKeys.CLI_PARSER_SUBSTITUTIONS);
ArgumentsParser parser = new ArgumentsParser(props, "module");
parser.getSubstitutions().putAll(substitutions);
parser.parse(args);
argModuleMap = parser.getParsedArgs();
if((Boolean)argModuleMap.get("help")) {
System.out.format("Usage: %s", parser.getUsage());
throw new ExitException("Help", 0);
}
if(!parser.getErrors().isEmpty()) {
for(Throwable t : parser.getErrors()) {
log.error(t.getMessage());
}
throw new ExitException("Parsing error", 1);
}
if (args.size() < 1) {
log.error("Action not provided");
throw new ExitException("Action not provided", 1);
}
try {
action = Action.valueOf(args.get(0).toUpperCase().replace("-", "_"));
} catch(IllegalArgumentException e) {
log.error("Invalid action '{}'", args.get(0));
throw new ExitException("Invalid action", 1);
}
argMap = action.parse(substitutions, props, args);
}
@Override
public void run() throws Exception {
action.execute(this);
}
}