
automately.core.Automately Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of automately-core Show documentation
Show all versions of automately-core Show documentation
A Scalable Web Application Platform
package automately.core;
import automately.core.data.Job;
import automately.core.data.Meta;
import automately.core.data.User;
import automately.core.file.VirtualFile;
import automately.core.file.VirtualFileService;
import automately.core.services.api.ApiServer;
import automately.core.services.container.ContainerService;
import automately.core.services.core.AutomatelyService;
import automately.core.services.ssh.SSHDaemonService;
import automately.core.services.job.JobServer;
import automately.core.services.job.script.objects.network.http.HttpServerService;
import automately.core.services.sdk.SdkSockJSServer;
import automately.core.services.sdk.eventbus.SdkAuthManager;
import automately.core.services.sdk.eventbus.SdkEventManager;
import automately.core.data.UserData;
import com.hazelcast.core.IMap;
import io.jsync.app.ClusterApp;
import io.jsync.app.core.Cluster;
import io.jsync.app.core.Config;
import io.jsync.app.core.Logger;
import io.jsync.app.core.service.ClusterService;
import io.jsync.json.JsonObject;
import io.jsync.utils.Token;
import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* Automately is a {@link io.jsync.app.ClusterApp}
*/
public class Automately extends ClusterApp {
static {
// By default we don't want hazelcast to phone home
System.setProperty("hazelcast.phone.home.enabled", "false");
System.setProperty("async.pool.eventloop.size", String.valueOf(Runtime.getRuntime().availableProcessors() * 5));
System.setProperty("async.pool.worker.size", String.valueOf(Runtime.getRuntime().availableProcessors() * 20));
}
/**
* Running this will result in the initialization of the default Automately instance
* and will join the cluster by default.
*
* @param args the jcluster arguments that you want to use
* @throws Exception
*/
public static void main(final String[] args) {
System.out.println("Automately Core Version: " + getVersion());
// We must initialize the jsync.io cluster app properly
ClusterApp.initialize(new Automately(), ArrayUtils.add(args, "--join"));
}
/**
* getBackendVersion() is a useful method to return the of the Automately Backend.
* @return
*/
public static String getVersion() {
try {
Properties properties = new Properties();
properties.load(Automately.class.getResourceAsStream("application.properties"));
return String.valueOf(properties.get("automately.core.version"));
} catch (Exception ignored) {
}
return "debugBuild";
}
@Override
public void prepareConfig(Config config) {
if (config.isDefault()) {
config.setRole("all");
}
if (!config.rawConfig().containsField("automately")) {
config.rawConfig().putObject("automately", new JsonObject());
}
if (!config.rawConfig().getObject("automately").containsField("core")) {
config.rawConfig().getObject("automately")
.putObject("core", new JsonObject());
}
}
@Override
public void prepareCluster(Cluster cluster) {
Logger logger = cluster().logger();
/**
* This {@link io.jsync.app.core.ClusterService} is required so we can initialize some things
* at the startup of the cluster. This is IMPORTANT.
*/
ClusterService baseService = new AutomatelyService() {
@Override
public String name() {
return "AutomatelyBaseServices";
}
@Override
public void start(Cluster cluster) {
logger.info("Initializing the default data indexes...");
IMap users = cluster().data().persistentMap("users");
IMap userMeta = cluster().data().persistentMap("users.meta");
IMap jobs = cluster().data().persistentMap("jobs");
IMap files = cluster().data().persistentMap("files");
users.addIndex("token", false);
users.addIndex("username", false);
users.addIndex("created", true);
userMeta.addIndex("userToken", false);
userMeta.addIndex("key", false);
jobs.addIndex("userToken", false);
jobs.addIndex("token", false);
jobs.addIndex("service", false);
jobs.addIndex("lite", false);
jobs.addIndex("status", false);
jobs.addIndex("updated", true);
files.addIndex("userToken", false);
files.addIndex("token", false);
files.addIndex("name", false);
files.addIndex("pathAlias", false);
files.addIndex("updated", true);
files.addIndex("isPublic", false);
logger.info("Checking the cluster for \"admin\" user.");
// This line will ensure that all the user data is loaded in the cluster
// We do this just to make sure that it happens. This is necessarily needed.
cluster.data().persistentMap("users");
// This basically tells the cluster
if(!cluster.hazelcast().getPartitionService().isClusterSafe()){
// Let's go ahead and start up some stuff
// If the cluster is big it may take up to 10 minutes for it to be ready
cluster.hazelcast().getPartitionService().forceLocalMemberToBeSafe(10, TimeUnit.MINUTES);
}
// Honestly we really don't care what server we are.
// We still need a darn admin user.
if (UserData.getUserByUsername("admin") == null) { // We want to ensure the data member creates this user
logger.warn("The \"admin\" user was not found so we are creating it for you.");
User user = new User();
user.username = "admin";
user.admin = true;
user.enabled = true;
users().set(user.token(), user);
// For security reasons we want to generate a random password.
String defaultPassword = Token.generateToken().toString() + Token.generateToken().toString();
UserData.setUserPassword(user, defaultPassword);
UserData.setMetaDefaults(user);
logger.info("The default \"admin\" user password is \"" + defaultPassword + "\".");
logger.info("The \"admin\" user private key is " + user.key);
logger.info("The \"admin\" user public key is " + user.publicKey);
}
User adminUser = UserData.getUserByUsername("admin");
if (adminUser != null) {
// This is a failsafe just in case a password was not set.
if (!UserData.containsMeta(adminUser, "password")) {
String defaultPassword = Token.generateToken().toString() + Token.generateToken().toString();
logger.info("The default \"admin\" user password is \"" + defaultPassword + "\".");
UserData.setUserPassword(adminUser, defaultPassword);
UserData.setMetaDefaults(adminUser);
}
}
if (!cluster.data().getMap("global.temp.data").containsKey("systemStart")) {
cluster.data().getMap("global.temp.data").put("systemStart", new Date().getTime());
}
}
@Override
public void stop() {
}
};
try {
Config config = cluster.config();
cluster.addService(baseService);
/**
* Add VirtualFileSupport. This needs to be on every member of the cluster and loaded before any other member
*/
cluster.addService(new VirtualFileService());
cluster.addService(new HttpServerService());
// This service is very important for container support
// and only needs to be started on members utilizing the JobServer.
if(config.isAll() || config.isRole("job")){
cluster.addService(new ContainerService());
}
// JCluster Roles: default, all, client, data
// Automately Roles: all, api, job, screenshot
// All members of the cluster have the JobServer service
// We don't need to add special services for the job
cluster.addService(new JobServer());
// TODO add a hazelcast only member
if (config.isRole("api")) {
cluster.addService(new SSHDaemonService());
cluster.addService(new ApiServer());
cluster.addService(new SdkAuthManager());
cluster.addService(new SdkEventManager());
cluster.addService(new SdkSockJSServer());
} else if (config.isRole("sdk")) {
cluster.addService(new SdkAuthManager());
cluster.addService(new SdkEventManager());
cluster.addService(new SdkSockJSServer());
} else if (config.isAll()) {
// Experimental support for now
cluster.addService(new SSHDaemonService());
// API Server
cluster.addService(new ApiServer());
// SDK Server
cluster.addService(new SdkAuthManager());
cluster.addService(new SdkEventManager());
cluster.addService(new SdkSockJSServer());
}
} catch (Exception e) {
throw new RuntimeException("There was an issue while attempting to prepare the cluster.", e);
}
}
/**
* This is a helper method to return the core automately configuration
*
* @return returns a JsonObject that contains all the data in {automately:{core:{}}}
*/
private JsonObject coreConfig() {
return cluster().config().rawConfig().getObject("automately").getObject("core");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy