Make CLI options configurable via environmental variables (#2408)

This commit is contained in:
Naoki Takezoe
2019-12-29 01:21:26 +09:00
committed by GitHub
parent d939082e1f
commit 04bc92001f
7 changed files with 97 additions and 67 deletions

View File

@@ -16,12 +16,17 @@ public class JettyLauncher {
System.setProperty("java.awt.headless", "true"); System.setProperty("java.awt.headless", "true");
String host = null; String host = null;
int port = 8080; String port = null;
InetSocketAddress address = null; InetSocketAddress address = null;
String contextPath = "/"; String contextPath = "/";
String tmpDirPath=""; String tmpDirPath="";
boolean forceHttps = false; boolean forceHttps = false;
host = getEnvironmentVariable("gitbucket.host");
port = getEnvironmentVariable("gitbucket.port");
contextPath = getEnvironmentVariable("gitbucket.prefix");
tmpDirPath = getEnvironmentVariable("gitbucket.tempDir");
for(String arg: args) { for(String arg: args) {
if(arg.startsWith("--") && arg.contains("=")) { if(arg.startsWith("--") && arg.contains("=")) {
String[] dim = arg.split("="); String[] dim = arg.split("=");
@@ -31,13 +36,10 @@ public class JettyLauncher {
host = dim[1]; host = dim[1];
break; break;
case "--port": case "--port":
port = Integer.parseInt(dim[1]); port = dim[1];
break; break;
case "--prefix": case "--prefix":
contextPath = dim[1]; contextPath = dim[1];
if (!contextPath.startsWith("/")) {
contextPath = "/" + contextPath;
}
break; break;
case "--max_file_size": case "--max_file_size":
System.setProperty("gitbucket.maxFileSize", dim[1]); System.setProperty("gitbucket.maxFileSize", dim[1]);
@@ -62,10 +64,14 @@ public class JettyLauncher {
} }
} }
if (contextPath != null && !contextPath.startsWith("/")) {
contextPath = "/" + contextPath;
}
if(host != null) { if(host != null) {
address = new InetSocketAddress(host, port); address = new InetSocketAddress(host, getPort(port));
} else { } else {
address = new InetSocketAddress(port); address = new InetSocketAddress(getPort(port));
} }
Server server = new Server(address); Server server = new Server(address);
@@ -143,6 +149,23 @@ public class JettyLauncher {
return new File(System.getProperty("user.home"), ".gitbucket"); return new File(System.getProperty("user.home"), ".gitbucket");
} }
private static String getEnvironmentVariable(String key){
String value = System.getenv(key.toUpperCase().replace('.', '_'));
if (value != null && value.length() == 0){
return null;
} else {
return value;
}
}
private static int getPort(String port){
if(port == null) {
return 8080;
} else {
return Integer.parseInt(port);
}
}
private static Handler addStatisticsHandler(Handler handler) { private static Handler addStatisticsHandler(Handler handler) {
// The graceful shutdown is implemented via the statistics handler. // The graceful shutdown is implemented via the statistics handler.
// See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142 // See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142

View File

@@ -15,7 +15,7 @@ import gitbucket.core.service.ProtectedBranchService.ProtectedBranchReceiveHook
import gitbucket.core.service.RepositoryService.RepositoryInfo import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service.SystemSettingsService import gitbucket.core.service.SystemSettingsService
import gitbucket.core.service.SystemSettingsService.SystemSettings import gitbucket.core.service.SystemSettingsService.SystemSettings
import gitbucket.core.util.DatabaseConfig import gitbucket.core.util.{ConfigUtil, DatabaseConfig}
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import io.github.gitbucket.solidbase.Solidbase import io.github.gitbucket.solidbase.Solidbase
import io.github.gitbucket.solidbase.manager.JDBCVersionManager import io.github.gitbucket.solidbase.manager.JDBCVersionManager
@@ -235,7 +235,7 @@ object PluginRegistry {
.reverse .reverse
} }
lazy val extraPluginDir: Option[String] = Option(System.getProperty("gitbucket.pluginDir")) lazy val extraPluginDir: Option[String] = ConfigUtil.getConfigValue[String]("gitbucket.pluginDir")
def getGitBucketVersion(pluginJarFileName: String): Option[String] = { def getGitBucketVersion(pluginJarFileName: String): Option[String] = {
val regex = ".+-gitbucket\\_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r val regex = ".+-gitbucket\\_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r

View File

@@ -305,7 +305,7 @@ object SystemSettingsService {
private val PluginProxyPassword = "plugin.proxy.password" private val PluginProxyPassword = "plugin.proxy.password"
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
getSystemProperty(key).getOrElse(getEnvironmentVariable(key).getOrElse { getConfigValue(key).getOrElse {
defining(props.getProperty(key)) { value => defining(props.getProperty(key)) { value =>
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
default default
@@ -313,11 +313,11 @@ object SystemSettingsService {
convertType(value).asInstanceOf[A] convertType(value).asInstanceOf[A]
} }
} }
}) }
} }
private def getOptionValue[A: ClassTag](props: java.util.Properties, key: String, default: Option[A]): Option[A] = { private def getOptionValue[A: ClassTag](props: java.util.Properties, key: String, default: Option[A]): Option[A] = {
getSystemProperty(key).orElse(getEnvironmentVariable(key).orElse { getConfigValue(key).orElse {
defining(props.getProperty(key)) { value => defining(props.getProperty(key)) { value =>
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
default default
@@ -325,7 +325,7 @@ object SystemSettingsService {
Some(convertType(value)).asInstanceOf[Option[A]] Some(convertType(value)).asInstanceOf[Option[A]]
} }
} }
}) }
} }
} }

View File

@@ -0,0 +1,41 @@
package gitbucket.core.util
import gitbucket.core.util.SyntaxSugars.defining
import scala.reflect.ClassTag
object ConfigUtil {
def getConfigValue[A: ClassTag](key: String): Option[A] = {
getSystemProperty(key).orElse(getEnvironmentVariable(key))
}
def getEnvironmentVariable[A: ClassTag](key: String): Option[A] = {
val name = (if (key.startsWith("gitbucket.")) "" else "GITBUCKET_") + key.toUpperCase.replace('.', '_')
val value = System.getenv(name)
if (value != null && value.nonEmpty) {
Some(convertType(value))
} else {
None
}
}
def getSystemProperty[A: ClassTag](key: String): Option[A] = {
val name = if (key.startsWith("gitbucket.")) key else "gitbucket." + key
val value = System.getProperty(name)
if (value != null && value.nonEmpty) {
Some(convertType(value))
} else {
None
}
}
def convertType[A: ClassTag](value: String): A =
defining(implicitly[ClassTag[A]].runtimeClass) { c =>
if (c == classOf[Boolean]) value.toBoolean
else if (c == classOf[Long]) value.toLong
else if (c == classOf[Int]) value.toInt
else value
}.asInstanceOf[A]
}

View File

@@ -6,7 +6,6 @@ import java.io.File
import Directory._ import Directory._
import ConfigUtil._ import ConfigUtil._
import com.github.takezoe.slick.blocking.{BlockingH2Driver, BlockingJdbcProfile, BlockingMySQLDriver} import com.github.takezoe.slick.blocking.{BlockingH2Driver, BlockingJdbcProfile, BlockingMySQLDriver}
import gitbucket.core.util.SyntaxSugars.defining
import liquibase.database.AbstractJdbcDatabase import liquibase.database.AbstractJdbcDatabase
import liquibase.database.core.{H2Database, MySQLDatabase, PostgresDatabase} import liquibase.database.core.{H2Database, MySQLDatabase, PostgresDatabase}
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
@@ -54,16 +53,14 @@ object DatabaseConfig {
lazy val minimumIdle: Option[Int] = getOptionValue("db.minimumIdle", config.getInt) lazy val minimumIdle: Option[Int] = getOptionValue("db.minimumIdle", config.getInt)
lazy val maximumPoolSize: Option[Int] = getOptionValue("db.maximumPoolSize", config.getInt) lazy val maximumPoolSize: Option[Int] = getOptionValue("db.maximumPoolSize", config.getInt)
private def getValue[T](path: String, f: String => T): T = { private def getValue[T: ClassTag](path: String, f: String => T): T = {
getSystemProperty(path).getOrElse(getEnvironmentVariable(path).getOrElse { getConfigValue(path).getOrElse(f(path))
f(path)
})
} }
private def getOptionValue[T](path: String, f: String => T): Option[T] = { private def getOptionValue[T: ClassTag](path: String, f: String => T): Option[T] = {
getSystemProperty(path).orElse(getEnvironmentVariable(path).orElse { getConfigValue(path).orElse {
if (config.hasPath(path)) Some(f(path)) else None if (config.hasPath(path)) Some(f(path)) else None
}) }
} }
} }
@@ -114,33 +111,3 @@ object DatabaseType {
} }
} }
} }
object ConfigUtil {
def getEnvironmentVariable[A](key: String): Option[A] = {
val value = System.getenv("GITBUCKET_" + key.toUpperCase.replace('.', '_'))
if (value != null && value.nonEmpty) {
Some(convertType(value)).asInstanceOf[Option[A]]
} else {
None
}
}
def getSystemProperty[A](key: String): Option[A] = {
val value = System.getProperty("gitbucket." + key)
if (value != null && value.nonEmpty) {
Some(convertType(value)).asInstanceOf[Option[A]]
} else {
None
}
}
def convertType[A: ClassTag](value: String) =
defining(implicitly[ClassTag[A]].runtimeClass) { c =>
if (c == classOf[Boolean]) value.toBoolean
else if (c == classOf[Long]) value.toLong
else if (c == classOf[Int]) value.toInt
else value
}
}

View File

@@ -92,16 +92,12 @@ object FileUtil {
name name
} }
lazy val MaxFileSize = lazy val MaxFileSize: Long = {
if (System.getProperty("gitbucket.maxFileSize") != null) ConfigUtil.getConfigValue[Long]("gitbucket.maxFileSize").getOrElse(3 * 1024 * 1024)
System.getProperty("gitbucket.maxFileSize").toLong }
else
3 * 1024 * 1024
lazy val UploadTimeout = lazy val UploadTimeout: Long = {
if (System.getProperty("gitbucket.UploadTimeout") != null) ConfigUtil.getConfigValue[Long]("gitbucket.UploadTimeout").getOrElse(3 * 10000)
System.getProperty("gitbucket.UploadTimeout").toLong }
else
3 * 10000
} }

View File

@@ -8,7 +8,7 @@ trait Validations {
/** /**
* Constraint for the identifier such as user name or page name. * Constraint for the identifier such as user name or page name.
*/ */
def identifier: Constraint = new Constraint() { val identifier: Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = override def validate(name: String, value: String, messages: Messages): Option[String] =
if (!value.matches("[a-zA-Z0-9\\-_.]+")) { if (!value.matches("[a-zA-Z0-9\\-_.]+")) {
Some(s"${name} contains invalid character.") Some(s"${name} contains invalid character.")
@@ -22,19 +22,22 @@ trait Validations {
/** /**
* Constraint for the password. * Constraint for the password.
*/ */
def password: Constraint = new Constraint() { val password: Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = lazy val validatePassword = ConfigUtil.getConfigValue[Boolean]("gitbucket.validate.password").getOrElse(true)
if (System.getProperty("gitbucket.validate.password") != "false" && !value.matches("[a-zA-Z0-9\\-_.]+")) {
override def validate(name: String, value: String, messages: Messages): Option[String] = {
if (validatePassword == true && !value.matches("[a-zA-Z0-9\\-_.]+")) {
Some(s"${name} contains invalid character.") Some(s"${name} contains invalid character.")
} else { } else {
None None
} }
}
} }
/** /**
* Constraint for the repository identifier. * Constraint for the repository identifier.
*/ */
def repository: Constraint = new Constraint() { val repository: Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = override def validate(name: String, value: String, messages: Messages): Option[String] =
if (!value.matches("[a-zA-Z0-9\\-\\+_.]+")) { if (!value.matches("[a-zA-Z0-9\\-\\+_.]+")) {
Some(s"${name} contains invalid character.") Some(s"${name} contains invalid character.")
@@ -48,7 +51,7 @@ trait Validations {
/** /**
* Constraint for the color pattern. * Constraint for the color pattern.
*/ */
def color = pattern("#[0-9a-fA-F]{6}") val color = pattern("#[0-9a-fA-F]{6}")
/** /**
* ValueType for the java.util.Date property. * ValueType for the java.util.Date property.