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