001package io.ebean.docker.commands; 002 003import io.ebean.docker.commands.process.ProcessHandler; 004import io.ebean.docker.commands.process.ProcessResult; 005import io.ebean.docker.container.Container; 006 007import java.util.ArrayList; 008import java.util.List; 009import java.util.Properties; 010 011/** 012 * Commands for controlling a DB2 docker container. 013 */ 014public class Db2Container extends JdbcBaseDbContainer implements Container { 015 016 public static Db2Container create(String Db2Version, Properties properties) { 017 return new Db2Container(new Db2Config(Db2Version, properties)); 018 } 019 020 public Db2Container(Db2Config config) { 021 super(config); 022 this.waitForConnectivityAttempts = 2000; 023 } 024 025 @Override 026 void createDatabase() { 027 if (checkConnectivity(false)) { 028 return; // container with DB & userName already running - do not recreate DB 029 } 030 // #1 Do user management (as root) 031 try { 032 dockerSu("root", "useradd -g db2iadm1 " + dbConfig.getUsername()); 033 } catch (CommandException e) { 034 e.getResult().getOutLines().forEach(log::warn); 035 } 036 dockerSu("root", "echo \"" + dbConfig.getUsername() + ":" + dbConfig.getPassword() + "\" | chpasswd"); 037 038 // #2 create database (with optional create options) 039 String cmd = "db2 create database " + dbConfig.getDbName(); 040 if (defined(((Db2Config) dbConfig).getCreateOptions())) { 041 cmd = cmd + " " + ((Db2Config) dbConfig).getCreateOptions(); 042 } 043 dockerSu(cmd); 044 045 // #3 set optional config options 046 if (defined(((Db2Config) dbConfig).getConfigOptions())) { 047 cmd = "db2 update database config for " + dbConfig.getDbName() + " " + ((Db2Config) dbConfig).getConfigOptions(); 048 dockerSu(dbConfig.getAdminUsername(), cmd); 049 } 050 051 // #4 activate database 052 cmd = "db2 activate database " + dbConfig.getDbName(); 053 dockerSu(cmd); 054 055 // #5 set recommended values for database 056 cmd = "/var/db2_setup/lib/set_rec_values.sh " + dbConfig.getDbName(); 057 dockerSu(cmd); 058 } 059 060 @Override 061 void dropCreateDatabase() { 062 try { 063 dockerSu("db2 drop database " + dbConfig.getDbName()); 064 } catch (CommandException e) { 065 // may fail, if database does not exist 066 e.getResult().getOutLines().forEach(log::warn); 067 } 068 createDatabase(); 069 } 070 071 @Override 072 protected ProcessBuilder runProcess() { 073 074 List<String> args = dockerRun(); 075 args.add("--privileged"); // this container needs extended permissions 076 args.add("-e"); 077 args.add("LICENSE=accept"); 078 079 args.add("-e"); 080 args.add("SAMPLEDB=false"); 081 082 args.add("-e"); 083 args.add("ARCHIVE_LOGS=false"); 084 // (default: true) Specify false to not configure log archiving (reduces start 085 // up time) 086 087 args.add("-e"); 088 args.add("AUTOCONFIG=false"); 089 // (default: true) Specify false to not run auto configuration on the instance 090 // and database (reduces start up time) 091 092 // set admin user & pw - but do not create a database 093 args.add("-e"); 094 args.add("DB2INSTANCE=" + dbConfig.getAdminUsername()); 095 096 if (defined(dbConfig.getAdminPassword())) { 097 args.add("-e"); 098 args.add("DB2INST1_PASSWORD=" + dbConfig.getAdminPassword()); 099 } 100 args.add("-e"); 101 args.add("DBNAME="); 102 args.add(config.getImage()); 103 return createProcessBuilder(args); 104 } 105 106 /** 107 * Runs the given (linux) command inside the container as given user. 108 */ 109 protected List<String> dockerSu(String user, String cmd) { 110 List<String> args = new ArrayList<>(); 111 args.add(config.docker); 112 args.add("exec"); 113 args.add("-i"); 114 args.add(config.containerName()); 115 args.add("su"); 116 args.add("-"); 117 args.add(user); 118 args.add("-c"); 119 args.add(cmd); 120 ProcessBuilder pb = createProcessBuilder(args); 121 ProcessResult pr = ProcessHandler.process(pb); 122 pr.getOutLines().forEach(log::debug); 123 return pr.getOutLines(); 124 } 125 126 /** 127 * Executes the (linux) command as DB-admin user. 128 */ 129 protected List<String> dockerSu(String cmd) { 130 return dockerSu(dbConfig.getAdminUsername(), cmd); 131 } 132 133 /** 134 * used to detect, when the container is up. This does not mean, you can already 135 * connect with JDBC. You must create the database first. 136 */ 137 @Override 138 boolean checkConnectivity() { 139 try { 140 List<String> result = dockerSu("db2pd -"); 141 142 for (String outLine : result) { 143 if (outLine.contains("-- Active --")) { 144 return true; 145 } 146 } 147 return false; 148 } catch (Throwable t) { 149 return false; 150 } 151 } 152}