Details
diff --git a/azkaban-common/src/main/java/azkaban/database/AzkabanDatabaseSetup.java b/azkaban-common/src/main/java/azkaban/database/AzkabanDatabaseSetup.java
index eb59246..d24422f 100644
--- a/azkaban-common/src/main/java/azkaban/database/AzkabanDatabaseSetup.java
+++ b/azkaban-common/src/main/java/azkaban/database/AzkabanDatabaseSetup.java
@@ -166,8 +166,7 @@ public class AzkabanDatabaseSetup {
File dbPropsFile = new File(this.scriptPath, "database.properties");
if (!dbPropsFile.exists()) {
- throw new IOException("Cannot find 'database.properties' file in "
- + dbPropsFile.getPath());
+ throw new IOException("Cannot find 'database.properties' file in " + dbPropsFile.getAbsolutePath());
}
return new Props(null, dbPropsFile);
diff --git a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
index a669d25..2ce08b5 100644
--- a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
+++ b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecutorServer.java
@@ -42,6 +42,7 @@ import azkaban.utils.Utils;
import com.google.common.base.Throwables;
import com.google.inject.Guice;
import com.google.inject.Inject;
+import com.google.inject.Injector;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -339,28 +340,16 @@ public class AzkabanExecutorServer {
return;
}
-
/* Initialize Guice Injector */
- SERVICE_PROVIDER.setInjector(Guice.createInjector(
- new AzkabanCommonModule(props),
- new AzkabanExecServerModule()
- ));
+ final Injector injector = Guice.createInjector(new AzkabanCommonModule(props), new AzkabanExecServerModule());
+ SERVICE_PROVIDER.setInjector(injector);
- launch(props);
+ launch(injector.getInstance(AzkabanExecutorServer.class));
}
- public static void launch(Props azkabanSettings) throws Exception {
- // Setup time zone
- if (azkabanSettings.containsKey(DEFAULT_TIMEZONE_ID)) {
- String timezone = azkabanSettings.getString(DEFAULT_TIMEZONE_ID);
- System.setProperty("user.timezone", timezone);
- TimeZone.setDefault(TimeZone.getTimeZone(timezone));
- DateTimeZone.setDefault(DateTimeZone.forID(timezone));
-
- logger.info("Setting timezone to " + timezone);
- }
-
- app = SERVICE_PROVIDER.getInstance(AzkabanExecutorServer.class);
+ public static void launch(AzkabanExecutorServer azkabanExecutorServer) throws Exception {
+ setupTimeZone(azkabanExecutorServer.getAzkabanProps());
+ app = azkabanExecutorServer;
Runtime.getRuntime().addShutdownHook(new Thread() {
@@ -413,6 +402,17 @@ public class AzkabanExecutorServer {
});
}
+ private static void setupTimeZone(Props azkabanSettings) {
+ if (azkabanSettings.containsKey(DEFAULT_TIMEZONE_ID)) {
+ String timezone = azkabanSettings.getString(DEFAULT_TIMEZONE_ID);
+ System.setProperty("user.timezone", timezone);
+ TimeZone.setDefault(TimeZone.getTimeZone(timezone));
+ DateTimeZone.setDefault(DateTimeZone.forID(timezone));
+
+ logger.info("Setting timezone to " + timezone);
+ }
+ }
+
public FlowRunnerManager getFlowRunnerManager() {
return runnerManager;
}
diff --git a/azkaban-solo-server/src/main/java/azkaban/soloserver/AzkabanSingleServer.java b/azkaban-solo-server/src/main/java/azkaban/soloserver/AzkabanSingleServer.java
index 6d0b6ca..7a0c306 100644
--- a/azkaban-solo-server/src/main/java/azkaban/soloserver/AzkabanSingleServer.java
+++ b/azkaban-solo-server/src/main/java/azkaban/soloserver/AzkabanSingleServer.java
@@ -20,6 +20,8 @@ import azkaban.AzkabanCommonModule;
import azkaban.execapp.AzkabanExecServerModule;
import azkaban.webapp.AzkabanWebServerModule;
import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
import org.apache.log4j.Logger;
import azkaban.database.AzkabanDatabaseSetup;
@@ -33,15 +35,32 @@ import static azkaban.ServiceProvider.*;
public class AzkabanSingleServer {
- private static final Logger logger = Logger.getLogger(AzkabanWebServer.class);
+ private static final Logger log = Logger.getLogger(AzkabanWebServer.class);
+
+ private final AzkabanWebServer webServer;
+ private final AzkabanExecutorServer executor;
+
+ @Inject
+ public AzkabanSingleServer(AzkabanWebServer webServer, AzkabanExecutorServer executor) {
+ this.webServer = webServer;
+ this.executor = executor;
+ }
+
+ private void launch() throws Exception {
+ AzkabanWebServer.launch(webServer);
+ log.info("Azkaban Web Server started...");
+
+ AzkabanExecutorServer.launch(executor);
+ log.info("Azkaban Exec Server started...");
+ }
public static void main(String[] args) throws Exception {
- logger.info("Starting Azkaban Server");
+ log.info("Starting Azkaban Server");
Props props = AzkabanServer.loadProps(args);
if (props == null) {
- logger.error("Properties not found. Need it to connect to the db.");
- logger.error("Exiting...");
+ log.error("Properties not found. Need it to connect to the db.");
+ log.error("Exiting...");
return;
}
@@ -52,16 +71,14 @@ public class AzkabanSingleServer {
}
/* Initialize Guice Injector */
- SERVICE_PROVIDER.setInjector(Guice.createInjector(
+ final Injector injector = Guice.createInjector(
new AzkabanCommonModule(props),
new AzkabanWebServerModule(),
new AzkabanExecServerModule()
- ));
-
- AzkabanWebServer.launch(props);
- logger.info("Azkaban Web Server started...");
+ );
+ SERVICE_PROVIDER.setInjector(injector);
- AzkabanExecutorServer.launch(props);
- logger.info("Azkaban Exec Server started...");
+ /* Launch server */
+ injector.getInstance(AzkabanSingleServer.class).launch();
}
}
diff --git a/azkaban-solo-server/src/test/java/azkaban/soloserver/AzkabanSingleServerTest.java b/azkaban-solo-server/src/test/java/azkaban/soloserver/AzkabanSingleServerTest.java
new file mode 100644
index 0000000..2cd1035
--- /dev/null
+++ b/azkaban-solo-server/src/test/java/azkaban/soloserver/AzkabanSingleServerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2017 LinkedIn Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ */
+
+package azkaban.soloserver;
+
+import azkaban.AzkabanCommonModule;
+import azkaban.database.AzkabanDatabaseSetup;
+import azkaban.database.AzkabanDatabaseUpdater;
+import azkaban.execapp.AzkabanExecServerModule;
+import azkaban.utils.Props;
+import azkaban.webapp.AzkabanWebServerModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.apache.log4j.Logger;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import static azkaban.ServiceProvider.*;
+import static azkaban.executor.ExecutorManager.*;
+import static java.util.Objects.*;
+import static org.apache.commons.io.FileUtils.*;
+import static org.junit.Assert.*;
+
+
+public class AzkabanSingleServerTest {
+ private static final Logger log = Logger.getLogger(AzkabanSingleServerTest.class);
+ public static final String AZKABAN_DB_SQL_PATH = "azkaban-db/src/main/sql";
+
+ private static final Props props = new Props();
+
+ private static String getConfPath() {
+ final URL resource = AzkabanSingleServerTest.class.getClassLoader().getResource("conf");
+ return requireNonNull(resource).getPath();
+ }
+
+ private static String getSqlScriptsDir() throws IOException {
+ // Dummy because any resource file works.
+ Path resources = Paths.get(getConfPath()).getParent();
+ Path azkabanRoot = resources.getParent().getParent().getParent().getParent();
+
+ File sqlScriptDir = Paths.get(azkabanRoot.toString(), AZKABAN_DB_SQL_PATH).toFile();
+ return sqlScriptDir.getCanonicalPath();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ tearDown();
+
+ final String confPath = getConfPath();
+
+ props.put("database.type", "h2");
+ props.put("h2.path", "./h2");
+
+ props.put(AZKABAN_USE_MULTIPLE_EXECUTORS, "false");
+ props.put("server.port", "0");
+ props.put("jetty.port", "0");
+ props.put("server.useSSL", "true");
+ props.put("jetty.use.ssl", "false");
+ props.put("user.manager.xml.file", new File(confPath, "azkaban-users.xml").getPath());
+ props.put("executor.port", "12321");
+
+ String sqlScriptsDir = getSqlScriptsDir();
+ assertTrue(new File(sqlScriptsDir).isDirectory());
+ props.put(AzkabanDatabaseSetup.DATABASE_SQL_SCRIPT_DIR, sqlScriptsDir);
+ AzkabanDatabaseUpdater.runDatabaseUpdater(props, sqlScriptsDir, true);
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ deleteQuietly(new File("h2.mv.db"));
+ deleteQuietly(new File("h2.trace.db"));
+ deleteQuietly(new File("executor.port"));
+ deleteQuietly(new File("executions"));
+ deleteQuietly(new File("projects"));
+ }
+
+ @Test
+ public void testInjection() throws Exception {
+ SERVICE_PROVIDER.unsetInjector();
+ /* Initialize Guice Injector */
+ final Injector injector = Guice.createInjector(
+ new AzkabanCommonModule(props),
+ new AzkabanWebServerModule(),
+ new AzkabanExecServerModule()
+ );
+ SERVICE_PROVIDER.setInjector(injector);
+
+ /* Launch server */
+ assertNotNull(injector.getInstance(AzkabanSingleServer.class));
+
+ SERVICE_PROVIDER.unsetInjector();
+ }
+}
diff --git a/azkaban-solo-server/src/test/resources/conf/azkaban-users.xml b/azkaban-solo-server/src/test/resources/conf/azkaban-users.xml
new file mode 100644
index 0000000..a13035d
--- /dev/null
+++ b/azkaban-solo-server/src/test/resources/conf/azkaban-users.xml
@@ -0,0 +1,7 @@
+<azkaban-users>
+ <user username="azkaban" password="azkaban" roles="admin" groups="azkaban" />
+ <user username="metrics" password="metrics" roles="metrics"/>
+
+ <role name="admin" permissions="ADMIN" />
+ <role name="metrics" permissions="METRICS"/>
+</azkaban-users>
diff --git a/azkaban-solo-server/src/test/resources/log4j.properties b/azkaban-solo-server/src/test/resources/log4j.properties
new file mode 100644
index 0000000..705b927
--- /dev/null
+++ b/azkaban-solo-server/src/test/resources/log4j.properties
@@ -0,0 +1,13 @@
+log4j.rootLogger=INFO, Console
+log4j.logger.azkaban=INFO, server
+
+log4j.appender.server=org.apache.log4j.RollingFileAppender
+log4j.appender.server.layout=org.apache.log4j.PatternLayout
+log4j.appender.server.File=azkaban-webserver.log
+log4j.appender.server.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%c{1}] [Azkaban] %m%n
+log4j.appender.server.MaxFileSize=102400MB
+log4j.appender.server.MaxBackupIndex=2
+
+log4j.appender.Console=org.apache.log4j.ConsoleAppender
+log4j.appender.Console.layout=org.apache.log4j.PatternLayout
+log4j.appender.Console.layout.ConversionPattern=%d{yyyy/MM/dd HH:mm:ss.SSS Z} %p [%c{1}] [Azkaban] %m%n
diff --git a/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java b/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
index 012f08c..3e301e7 100644
--- a/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
+++ b/azkaban-web-server/src/main/java/azkaban/webapp/AzkabanWebServer.java
@@ -21,6 +21,7 @@ import com.codahale.metrics.MetricRegistry;
import com.google.inject.Guice;
import com.google.inject.Inject;
+import com.google.inject.Injector;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -683,20 +684,18 @@ public class AzkabanWebServer extends AzkabanServer {
}
/* Initialize Guice Injector */
- SERVICE_PROVIDER.setInjector(Guice.createInjector(
- new AzkabanCommonModule(props),
- new AzkabanWebServerModule()
- ));
+ final Injector injector = Guice.createInjector(new AzkabanCommonModule(props), new AzkabanWebServerModule());
+ SERVICE_PROVIDER.setInjector(injector);
- launch(props);
+ launch(injector.getInstance(AzkabanWebServer.class));
}
- public static void launch(Props azkabanSettings) throws Exception {
+ public static void launch(AzkabanWebServer webServer) throws Exception {
/* This creates the Web Server instance */
- app = SERVICE_PROVIDER.getInstance(AzkabanWebServer.class);
+ app = webServer;
// TODO refactor code into ServerProvider
- prepareAndStartServer(azkabanSettings, app.server);
+ prepareAndStartServer(webServer.getServerProps(), app.server);
Runtime.getRuntime().addShutdownHook(new Thread() {