package com.klarna.hiverunner.config;
import com.google.common.base.Preconditions;
import com.klarna.hiverunner.CommandShellEmulation;
import org.apache.hadoop.hive.conf.HiveConf;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* HiveRunner runtime configuration.
*
* Configure with System properties via mvn like
* <pre>
* {@literal <}plugin>
* <groupId>org.apache.maven.plugins</groupId>
* <artifactId>maven-surefire-plugin</artifactId>
* <version>2.17</version>
* <configuration>
* ...
* <systemProperties>
* <hiveconf_any.hive.conf>1000</hiveconf_any.hive.conf>
* <enableTimeout>false</enableTimeout>
* <timeoutSeconds>30</timeoutSeconds>
* <timeoutRetries>2</timeoutRetries>
* <commandShellEmulation>BEELINE</commandShellEmulation>
* </systemProperties>
* </configuration>
* </plugin>
* </pre>
*
* Properties may be overridden per test class by annotating a <b>static</b> HiveRunnerConfig field like:
* <pre>
* @HiveRunnerSetup
* public final static HiveRunnerConfig config = new HiveRunnerConfig(){{
* setTimeoutEnabled(true);
* setTimeoutSeconds(15);
* setTimeoutRetries(2);
* setCommandShellEmulation(CommandShellEmulation.BEELINE);
* }};
* </pre>
* See {@link com.klarna.hiverunner.DisabledTimeoutTest}
*/
public class HiveRunnerConfig {
/**
* Enable timeout. Some versions of tez has proven to not always terminate. By enabling timeout,
* HiveRunner will kill the current query and attempt to retry the test case a configurable number of times.
*
* Defaults to disabled
*/
public static final String ENABLE_TIMEOUT_PROPERTY_NAME = "enableTimeout";
public static final boolean ENABLE_TIMEOUT_DEFAULT = false;
/**
* Seconds to wait for a query to terminate before triggering the timeout.
*
* Defaults to 30 seconds
*/
public static final String TIMEOUT_SECONDS_PROPERTY_NAME = "timeoutSeconds";
public static final int TIMEOUT_SECONDS_DEFAULT = 30;
/**
* Number of retries for a test case that keep timing out.
*
* Defaults to 2 retries
*/
public static final String TIMEOUT_RETRIES_PROPERTY_NAME = "timeoutRetries";
public static final int TIMEOUT_RETRIES_DEFAULT = 2;
/**
* Suffix used to flag a system property to be a hiveconf setting.
*/
public static final String HIVECONF_SYSTEM_OVERRIDE_PREFIX = "hiveconf_";
/**
* The shell's {@link CommandShellEmulation}.
*
* Defaults to {@code HIVE_CLI}
*/
public static final String COMMAND_SHELL_EMULATION_PROPERTY_NAME = "commandShellEmulation";
public static final String COMMAND_SHELL_EMULATION_DEFAULT = CommandShellEmulation.HIVE_CLI.name();
private Map<String, Object> config = new HashMap<>();
private Map<String, String> hiveConfSystemOverride = new HashMap<>();
/**
* Construct a HiveRunnerConfig that will override hiveConf with
* System properties of the format 'hiveconf_[hiveconf property name]'.
*/
public HiveRunnerConfig() {
this(System.getProperties());
}
/**
* Construct a HiveRunnerConfig that will override hiveConf with
* the given properties of the format 'hiveconf_[hiveconf property name]'.
*/
public HiveRunnerConfig(Properties systemProperties) {
config.put(ENABLE_TIMEOUT_PROPERTY_NAME, load(ENABLE_TIMEOUT_PROPERTY_NAME, ENABLE_TIMEOUT_DEFAULT, systemProperties));
config.put(TIMEOUT_RETRIES_PROPERTY_NAME, load(TIMEOUT_RETRIES_PROPERTY_NAME, TIMEOUT_RETRIES_DEFAULT, systemProperties));
config.put(TIMEOUT_SECONDS_PROPERTY_NAME, load(TIMEOUT_SECONDS_PROPERTY_NAME, TIMEOUT_SECONDS_DEFAULT, systemProperties));
config.put(COMMAND_SHELL_EMULATION_PROPERTY_NAME, load(COMMAND_SHELL_EMULATION_PROPERTY_NAME, COMMAND_SHELL_EMULATION_DEFAULT, systemProperties));
hiveConfSystemOverride = loadHiveConfSystemOverrides(systemProperties);
}
public boolean isTimeoutEnabled() {
return getBoolean(ENABLE_TIMEOUT_PROPERTY_NAME);
}
public int getTimeoutRetries() {
return getInteger(TIMEOUT_RETRIES_PROPERTY_NAME);
}
public int getTimeoutSeconds() {
return getInteger(TIMEOUT_SECONDS_PROPERTY_NAME);
}
/**
* Get the configured hive.execution.engine. If not set it will default to the default value of HiveConf
*/
public String getHiveExecutionEngine() {
String executionEngine = hiveConfSystemOverride.get(HiveConf.ConfVars.HIVE_EXECUTION_ENGINE.varname);
return executionEngine == null ? HiveConf.ConfVars.HIVE_EXECUTION_ENGINE.getDefaultValue() : executionEngine;
}
public Map<String, String> getHiveConfSystemOverride() {
return hiveConfSystemOverride;
}
/**
* Determines the statement parsing behaviour of the interactive shell. Provided to emulate slight differences
* between different clients.
*/
public CommandShellEmulation getCommandShellEmulation() {
return CommandShellEmulation.valueOf(getString(COMMAND_SHELL_EMULATION_PROPERTY_NAME).toUpperCase());
}
public void setTimeoutEnabled(boolean isEnabled) {
config.put(ENABLE_TIMEOUT_PROPERTY_NAME, isEnabled);
}
public void setTimeoutRetries(int retries) {
config.put(TIMEOUT_RETRIES_PROPERTY_NAME, retries);
}
public void setTimeoutSeconds(int timeout) {
config.put(TIMEOUT_SECONDS_PROPERTY_NAME, timeout);
}
public void setHiveExecutionEngine(String executionEngine) {
hiveConfSystemOverride.put(HiveConf.ConfVars.HIVE_EXECUTION_ENGINE.varname, executionEngine);
}
public void setCommandShellEmulation(CommandShellEmulation commandShellEmulation) {
config.put(COMMAND_SHELL_EMULATION_PROPERTY_NAME, commandShellEmulation.name());
}
/**
* Copy values from the inserted config to this config. Note that if properties has not been explicitly set,
* the defaults will apply.
*/
public void override(HiveRunnerConfig hiveRunnerConfig) {
this.config.putAll(hiveRunnerConfig.config);
this.hiveConfSystemOverride.putAll(hiveRunnerConfig.hiveConfSystemOverride);
}
private static boolean load(String property, boolean defaultValue, Properties sysProperties) {
String value = sysProperties.getProperty(property);
return value == null ? defaultValue : Boolean.parseBoolean(value);
}
private static String load(String property, String defaultValue, Properties sysProperties) {
String value = sysProperties.getProperty(property);
return value == null ? defaultValue : value;
}
private static int load(String property, int defaultValue, Properties sysProperties) {
String value = sysProperties.getProperty(property);
return value == null ? defaultValue : Integer.parseInt(value);
}
private boolean getBoolean(String key) {
return (boolean) config.get(key);
}
private int getInteger(String key) {
return (int) config.get(key);
}
private String getString(String key) {
return (String) config.get(key);
}
private static Map<String, String> loadHiveConfSystemOverrides(Properties systemProperties) {
Map<String, String> hiveConfSystemOverride = new HashMap<>();
for (String sysKey : systemProperties.stringPropertyNames()) {
if (sysKey.startsWith(HIVECONF_SYSTEM_OVERRIDE_PREFIX)) {
String hiveConfKey = sysKey.substring(HIVECONF_SYSTEM_OVERRIDE_PREFIX.length());
hiveConfSystemOverride.put(hiveConfKey, systemProperties.getProperty(sysKey));
}
}
return hiveConfSystemOverride;
}
}