001package io.ebean.docker.commands;
002
003import io.ebean.docker.container.ContainerConfig;
004
005import java.sql.Connection;
006import java.sql.SQLException;
007import java.util.Properties;
008
009/**
010 * Configuration for an DBMS like Postgres, MySql, Oracle, SQLServer
011 */
012public abstract class BaseConfig implements ContainerConfig {
013
014  /**
015   * The database platform.
016   * <p>
017   * Expected to be one of 'postgres','mysql', 'oracle' or 'sqlserver'.
018   */
019  protected final String platform;
020
021  /**
022   * Container name.
023   */
024  protected String containerName;
025
026  /**
027   * The exposed port.
028   */
029  protected int port;
030
031  /**
032   * The internal port.
033   */
034  protected int internalPort;
035
036  /**
037   * The exposed port.
038   */
039  protected int adminPort;
040
041  /**
042   * The internal port.
043   */
044  protected int adminInternalPort;
045
046  /**
047   * Image name.
048   */
049  protected String image;
050
051  /**
052   * The mode used when starting (create, dropCreate, container [only]).
053   */
054  protected StartMode startMode = StartMode.Create;
055
056  /**
057   * The mode used when stopping (stop, remove).
058   */
059  protected StopMode stopMode = StopMode.Stop;
060
061  /**
062   * Set when we want to automatically stop or remove the container via JVM shutdown hook.
063   */
064  protected StopMode shutdownMode = StopMode.None;
065
066  /**
067   * The character set to use.
068   */
069  protected String characterSet;
070
071  /**
072   * The collation to use.
073   */
074  protected String collation;
075
076  /**
077   * Maximum number of attempts to find the 'database ready to accept connections' log message in the container.
078   * <p>
079   * 100 attempts equates to 10 seconds.
080   * </p>
081   */
082  protected int maxReadyAttempts = 300;
083
084  /**
085   * Docker command.
086   */
087  protected String docker = "docker";
088
089  protected final String version;
090
091  BaseConfig(String platform, int port, int internalPort, String version) {
092    this.platform = platform;
093    this.port = port;
094    this.internalPort = internalPort;
095    this.containerName = "ut_" + platform;
096    this.image = platform + ":" + version;
097    this.version = version;
098  }
099
100  /**
101   * Return a description of the configuration.
102   */
103  @Override
104  public String startDescription() {
105    return "starting " + platform + " container:" + containerName + " port:" + port + " startMode:" + startMode;
106  }
107
108  @Override
109  public String stopDescription() {
110    return "stopping " + platform + " container:" + containerName + " stopMode:" + stopMode;
111  }
112
113  @Override
114  public String platform() {
115    return platform;
116  }
117
118  @Override
119  public String containerName() {
120    return containerName;
121  }
122
123  @Override
124  public String version() {
125    return version;
126  }
127
128  @Override
129  public void setStartMode(StartMode startMode) {
130    this.startMode = startMode;
131  }
132
133  @Override
134  public void setStopMode(StopMode stopMode) {
135    this.stopMode = stopMode;
136  }
137
138  @Override
139  public void setShutdownMode(StopMode shutdownMode) {
140    this.shutdownMode = shutdownMode;
141  }
142
143  /**
144   * Return a Connection to the database (make sure you close it).
145   */
146  @Override
147  public Connection createConnection() throws SQLException {
148    throw new IllegalStateException("Not valid for this type");
149  }
150
151  @Override
152  public Connection createConnectionNoSchema() throws SQLException {
153    throw new IllegalStateException("Not valid for this type");
154  }
155
156  @Override
157  public Connection createAdminConnection() throws SQLException {
158    throw new IllegalStateException("Not valid for this type");
159  }
160
161  @Override
162  public String jdbcUrl() {
163    throw new IllegalStateException("Not valid for this type");
164  }
165
166  @Override
167  public String jdbcAdminUrl() {
168    return jdbcUrl();
169  }
170
171  /**
172   * Load configuration from properties.
173   */
174  public BaseConfig setProperties(Properties properties) {
175    if (properties == null) {
176      return this;
177    }
178    docker = properties.getProperty("docker", docker);
179
180    containerName = prop(properties, "containerName", containerName);
181    image = prop(properties, "image", image);
182    port = prop(properties, "port", port);
183    internalPort = prop(properties, "internalPort", internalPort);
184    adminPort = prop(properties, "adminPort", adminPort);
185    adminInternalPort = prop(properties, "adminInternalPort", adminInternalPort);
186    characterSet = prop(properties, "characterSet", characterSet);
187    collation = prop(properties, "collation", collation);
188
189    String start = properties.getProperty("startMode", startMode.name());
190    startMode = StartMode.of(prop(properties, "startMode", start));
191
192    String stop = properties.getProperty("stopMode", stopMode.name());
193    stopMode = StopMode.of(prop(properties, "stopMode", stop));
194
195    String shutdown = properties.getProperty("shutdown", shutdownMode.name());
196    shutdownMode = StopMode.of(prop(properties, "shutdown", shutdown));
197
198    String maxVal = prop(properties, "maxReadyAttempts", null);
199    if (maxVal != null) {
200      try {
201        this.maxReadyAttempts = Integer.parseInt(maxVal);
202      } catch (NumberFormatException e) {
203        // ignore error
204      }
205    }
206    return this;
207  }
208
209  protected String prop(Properties properties, String key, String defaultValue) {
210    String val = properties.getProperty("ebean.test." + platform + "." + key, defaultValue);
211    return properties.getProperty(platform + "." + key, val);
212  }
213
214  protected int prop(Properties properties, String key, int defaultValue) {
215    String val = properties.getProperty("ebean.test." + platform + "." + key);
216    val = properties.getProperty(platform + "." + key, val);
217    return val == null ? defaultValue : Integer.parseInt(val);
218  }
219
220  /**
221   * Set the container name.
222   */
223  public BaseConfig setContainerName(String containerName) {
224    this.containerName = containerName;
225    return this;
226  }
227
228  /**
229   * Set the exposed port.
230   */
231  public BaseConfig setPort(int port) {
232    this.port = port;
233    return this;
234  }
235
236  /**
237   * Set the internal (to the container) port.
238   */
239  public BaseConfig setInternalPort(int internalPort) {
240    this.internalPort = internalPort;
241    return this;
242  }
243
244  /**
245   * Set the exposed admin port.
246   */
247  public BaseConfig setAdminPort(int adminPort) {
248    this.adminPort = adminPort;
249    return this;
250  }
251
252  /**
253   * Set the internal admin (to the container) port.
254   */
255  public BaseConfig setAdminInternalPort(int adminInternalPort) {
256    this.adminInternalPort = adminInternalPort;
257    return this;
258  }
259
260  /**
261   * Set the docker image to use.
262   */
263  public BaseConfig setImage(String image) {
264    this.image = image;
265    return this;
266  }
267
268  /**
269   * Set the character set to use.
270   */
271  public BaseConfig setCharacterSet(String characterSet) {
272    this.characterSet = characterSet;
273    return this;
274  }
275
276  /**
277   * Set the collation to use.
278   */
279  public BaseConfig setCollation(String collation) {
280    this.collation = collation;
281    return this;
282  }
283
284  /**
285   * Set the max attempts to wait for DB ready.
286   */
287  public BaseConfig setMaxReadyAttempts(int maxReadyAttempts) {
288    this.maxReadyAttempts = maxReadyAttempts;
289    return this;
290  }
291
292  /**
293   * Set the docker command to use (defaults to 'docker').
294   */
295  public BaseConfig setDocker(String docker) {
296    this.docker = docker;
297    return this;
298  }
299
300  public int getPort() {
301    return port;
302  }
303
304  public int getInternalPort() {
305    return internalPort;
306  }
307
308  public int getAdminPort() {
309    return adminPort;
310  }
311
312  public int getAdminInternalPort() {
313    return adminInternalPort;
314  }
315
316  public String getImage() {
317    return image;
318  }
319
320  public StartMode getStartMode() {
321    return startMode;
322  }
323
324  public StopMode getStopMode() {
325    return stopMode;
326  }
327
328  public int getMaxReadyAttempts() {
329    return maxReadyAttempts;
330  }
331
332  public String getDocker() {
333    return docker;
334  }
335
336  public StopMode shutdownMode() {
337    return shutdownMode;
338  }
339
340  public String getCharacterSet() {
341    return characterSet;
342  }
343
344  public String getCollation() {
345    return collation;
346  }
347
348  public boolean isExplicitCollation() {
349    return collation != null || characterSet != null;
350  }
351
352  public boolean isDefaultCollation() {
353    return "default".equals(collation);
354  }
355
356  public boolean isStopModeNone() {
357    return StopMode.None == stopMode;
358  }
359
360  /**
361   * Clear the stopMode when detect already running.
362   */
363  public void clearStopMode() {
364    this.stopMode = StopMode.None;
365  }
366}