001package io.ebean.docker.container;
002
003import io.ebean.docker.commands.ClickHouseContainer;
004import io.ebean.docker.commands.CockroachContainer;
005import io.ebean.docker.commands.ElasticContainer;
006import io.ebean.docker.commands.HanaContainer;
007import io.ebean.docker.commands.MariaDBContainer;
008import io.ebean.docker.commands.MySqlContainer;
009import io.ebean.docker.commands.NuoDBContainer;
010import io.ebean.docker.commands.OracleContainer;
011import io.ebean.docker.commands.PostgresContainer;
012import io.ebean.docker.commands.RedisContainer;
013import io.ebean.docker.commands.SqlServerContainer;
014
015import java.util.ArrayList;
016import java.util.HashSet;
017import java.util.List;
018import java.util.Properties;
019import java.util.Set;
020import java.util.function.Consumer;
021
022/**
023 * Creates containers from properties with the ability to start and stop them.
024 */
025public class ContainerFactory {
026
027  private final Properties properties;
028
029  private final List<Container> containers = new ArrayList<>();
030
031  private final Set<String> runWith = new HashSet<>();
032
033  private static String defaultRunWith() {
034    String runWith = System.getenv("DOCKER_RUN_WITH");
035    return System.getProperty("docker_run_with", runWith);
036  }
037
038  /**
039   * Create given properties and reading system and env properties for 'run with'.
040   */
041  public ContainerFactory(Properties properties) {
042    this(properties, defaultRunWith());
043  }
044
045  /**
046   * Create given the properties and runWith.
047   *
048   * @param properties The properties to configure the containers
049   * @param runWith    Comma delimited string with container to run
050   */
051  public ContainerFactory(Properties properties, String runWith) {
052    this.properties = properties;
053    initRunWith(runWith);
054    init();
055  }
056
057  private void initRunWith(String runWithOptions) {
058    if (runWithOptions != null) {
059      for (String value : runWithOptions.split(",")) {
060        runWith.add(value.trim().toLowerCase());
061      }
062    }
063  }
064
065  private void init() {
066    String elasticVersion = version("elastic");
067    if (elasticVersion != null) {
068      containers.add(ElasticContainer.create(elasticVersion, properties));
069    }
070    String redisVersion = version("redis");
071    if (redisVersion != null) {
072      containers.add(RedisContainer.create(redisVersion, properties));
073    }
074    String pgVersion = runWithVersion("postgres");
075    if (pgVersion != null) {
076      containers.add(PostgresContainer.create(pgVersion, properties));
077    }
078    String mysqlVersion = runWithVersion("mysql");
079    if (mysqlVersion != null) {
080      containers.add(MySqlContainer.create(mysqlVersion, properties));
081    }
082    String mariadbVersion = runWithVersion("mariadb");
083    if (mariadbVersion != null) {
084      containers.add(MariaDBContainer.create(mariadbVersion, properties));
085    }
086    String nuodbVersion = runWithVersion("nuodb");
087    if (nuodbVersion != null) {
088      containers.add(NuoDBContainer.create(nuodbVersion, properties));
089    }
090    String sqlServerVersion = runWithVersion("sqlserver");
091    if (sqlServerVersion != null) {
092      containers.add(SqlServerContainer.create(sqlServerVersion, properties));
093    }
094    String oracleVersion = runWithVersion("oracle");
095    if (oracleVersion != null) {
096      containers.add(OracleContainer.create(oracleVersion, properties));
097    }
098    String hanaVersion = runWithVersion("hana");
099    if (hanaVersion != null) {
100      containers.add(HanaContainer.create(hanaVersion, properties));
101    }
102    String clickhouseVersion = runWithVersion("clickhouse");
103    if (clickhouseVersion != null) {
104      containers.add(ClickHouseContainer.create(clickhouseVersion, properties));
105    }
106    String cockroachVersion = runWithVersion("cockroach");
107    if (cockroachVersion != null) {
108      containers.add(CockroachContainer.create(cockroachVersion, properties));
109    }
110  }
111
112  /**
113   * Return the version if the container should be added.
114   * Filters out database containers using <code>runWith</code>.
115   */
116  String runWithVersion(String name) {
117    String version = version(name);
118    if (version == null) {
119      return null;
120    }
121    return (runWith.isEmpty() || runWith.contains(name)) ? version : null;
122  }
123
124  private String version(String prefix) {
125    return properties.getProperty(prefix + ".version");
126  }
127
128  /**
129   * Start all the containers.
130   */
131  public void startContainers() {
132    startContainers(null);
133  }
134
135  /**
136   * Start all the containers with a consumer for logging start descriptions.
137   */
138  public void startContainers(Consumer<String> logging) {
139    for (Container container : containers) {
140      if (logging != null) {
141        logging.accept(container.config().startDescription());
142      }
143      container.start();
144    }
145  }
146
147  /**
148   * Stop all containers using the stopMode which defaults to also removing the containers.
149   */
150  public void stopContainers() {
151    stopContainers(null);
152  }
153
154  /**
155   * Stop all the containers with a consumer for logging stop descriptions.
156   */
157  public void stopContainers(Consumer<String> logging) {
158
159    for (Container container : containers) {
160      if (logging != null) {
161        logging.accept(container.config().stopDescription());
162      }
163      container.stop();
164    }
165  }
166
167  /**
168   * Stop all containers (without removing the containers).
169   */
170  public void stopOnly() {
171    stopOnly(null);
172  }
173
174  /**
175   * Stop all the containers (without remove) with a consumer for logging stop descriptions.
176   */
177  public void stopOnly(Consumer<String> logging) {
178
179    for (Container container : containers) {
180      if (logging != null) {
181        logging.accept(container.config().stopDescription());
182      }
183      container.stopOnly();
184    }
185  }
186
187  /**
188   * Return the config for a given platform.
189   */
190  public ContainerConfig config(String platform) {
191    Container container = container(platform);
192    return (container == null) ? null : container.config();
193  }
194
195  /**
196   * Return the container for a given platform.
197   */
198  public Container container(String platform) {
199    for (Container container : containers) {
200      ContainerConfig config = container.config();
201      if (config.platform().equalsIgnoreCase(platform)) {
202        return container;
203      }
204    }
205    return null;
206  }
207}