Skip to content

Commit 0e7eb62

Browse files
committed
Refactor code and add logs
1 parent f186e74 commit 0e7eb62

File tree

3 files changed

+117
-95
lines changed

3 files changed

+117
-95
lines changed

src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java

Lines changed: 91 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
2727
import com.couchbase.client.java.query.Index;
2828
import lombok.AllArgsConstructor;
29+
import lombok.Cleanup;
2930
import lombok.Getter;
31+
import lombok.SneakyThrows;
3032
import lombok.experimental.Wither;
33+
import org.jetbrains.annotations.NotNull;
3134
import org.testcontainers.containers.GenericContainer;
3235
import org.testcontainers.containers.wait.HttpWaitStrategy;
3336

@@ -60,6 +63,7 @@ public class CouchbaseContainer<SELF extends CouchbaseContainer<SELF>> extends G
6063
private static final int ANALYTICS_PORT = 8095;
6164
private static final int ANALYTICS_SSL_PORT = 18095;
6265
//</editor-fold>
66+
public static final String DELIMITER = ",";
6367

6468
@Getter
6569
@Wither
@@ -115,6 +119,9 @@ public class CouchbaseContainer<SELF extends CouchbaseContainer<SELF>> extends G
115119
@Getter(lazy = true)
116120
private final CouchbaseCluster couchbaseCluster = createCouchbaseCluster();
117121

122+
@Getter(lazy = true)
123+
private final CouchbaseNodeWaitStrategy couchbaseNodeWaitStrategy = createCouchbaseWaitStrategy();
124+
118125
@Getter
119126
private static final Collection<CouchbaseContainer> containers = new HashSet<>();
120127

@@ -123,7 +130,8 @@ public class CouchbaseContainer<SELF extends CouchbaseContainer<SELF>> extends G
123130

124131
private List<BucketSettings> newBuckets = new ArrayList<>();
125132

126-
private String urlBase;
133+
@Getter(lazy = true)
134+
private final String urlBase = createUrlBase();
127135

128136
public CouchbaseContainer() {
129137
this("couchbase/server:latest");
@@ -136,7 +144,7 @@ public CouchbaseContainer(String containerName) {
136144

137145
@Override
138146
protected Integer getLivenessCheckPort() {
139-
return getMappedPort(CONFIG_PORT);
147+
return isSsl() ? getMappedPort(CONFIG_SSL_PORT) : getMappedPort(CONFIG_PORT);
140148
}
141149

142150
@Override
@@ -165,76 +173,101 @@ protected void configure() {
165173
addExposedPort(ANALYTICS_SSL_PORT);
166174
}
167175
}
168-
setWaitStrategy(new HttpWaitStrategy().forPath("/ui/index.html#/"));
176+
HttpWaitStrategy waitStrategy = new HttpWaitStrategy().forPath("/ui/index.html#/");
177+
setWaitStrategy(ssl ? waitStrategy.usingTls() : waitStrategy);
169178
}
170179

171180
public SELF withNewBucket(BucketSettings bucketSettings) {
172181
newBuckets.add(bucketSettings);
173182
return self();
174183
}
175184

176-
public void initCluster() {
177-
urlBase = String.format("http://%s:%s", getContainerIpAddress(), getMappedPort(CONFIG_PORT));
178-
try {
179-
String poolURL = "/pools/default";
180-
String poolPayload = "memoryQuota=" + URLEncoder.encode(memoryQuota, "UTF-8") + "&indexMemoryQuota=" + URLEncoder.encode(indexMemoryQuota, "UTF-8");
185+
@SneakyThrows
186+
public void init() {
187+
initCluster();
188+
initServices();
189+
initAdminUser();
190+
initSampleBuckets();
191+
this.getCouchbaseNodeWaitStrategy().waitUntilReady(this);
192+
initIndexes();
193+
this.getCouchbaseNodeWaitStrategy().waitUntilReady(this);
194+
}
181195

182-
String setupServicesURL = "/node/controller/setupServices";
183-
StringBuilder servicePayloadBuilder = new StringBuilder();
184-
if (keyValue) {
185-
servicePayloadBuilder.append("kv,");
186-
}
187-
if (query) {
188-
servicePayloadBuilder.append("n1ql,");
189-
}
190-
if (index) {
191-
servicePayloadBuilder.append("index,");
192-
}
193-
if (fts) {
194-
servicePayloadBuilder.append("fts,");
195-
}
196-
if (analytics) {
197-
servicePayloadBuilder.append("cbas,");
198-
}
199-
String setupServiceContent = "services=" + URLEncoder.encode(servicePayloadBuilder.toString(), "UTF-8");
196+
private void initCluster() throws IOException {
197+
logger().debug("Initializing couchbase cluster");
198+
String poolURL = "/pools/default";
199+
String poolPayload = "memoryQuota=" + URLEncoder.encode(memoryQuota, "UTF-8") + "&indexMemoryQuota=" + URLEncoder.encode(indexMemoryQuota, "UTF-8");
200+
callCouchbaseRestAPI(poolURL, poolPayload);
201+
}
202+
203+
private void initServices() throws IOException {
204+
StringJoiner services = new StringJoiner(DELIMITER);
205+
if (keyValue) {
206+
services.add("kv");
207+
}
208+
if (query) {
209+
services.add("n1ql");
210+
}
211+
if (index) {
212+
services.add("index");
213+
}
214+
if (fts) {
215+
services.add("fts");
216+
}
217+
if (analytics) {
218+
services.add("cbas");
219+
}
220+
logger().debug("Initializing services : {}", services.toString());
221+
callCouchbaseRestAPI("/node/controller/setupServices", "services=" + URLEncoder.encode(services.toString(), "UTF-8"));
222+
}
200223

201-
String webSettingsURL = "/settings/web";
202-
String webSettingsContent = "username=" + URLEncoder.encode(clusterUsername, "UTF-8") + "&password=" + URLEncoder.encode(clusterPassword, "UTF-8") + "&port=8091";
224+
private void initAdminUser() throws IOException {
225+
logger().debug("Creating cluster admin user '{}'", clusterUsername);
226+
callCouchbaseRestAPI("/settings/web",
227+
"username=" + URLEncoder.encode(clusterUsername, "UTF-8") + "&password=" + URLEncoder.encode(clusterPassword, "UTF-8") + "&port=8091");
228+
}
203229

204-
String bucketURL = "/sampleBuckets/install";
230+
private void initSampleBuckets() throws IOException {
231+
StringJoiner sampleBucketPayload = new StringJoiner(DELIMITER);
232+
if (travelSample) {
233+
sampleBucketPayload.add("\"travel-sample\"");
234+
}
235+
if (beerSample) {
236+
sampleBucketPayload.add("\"beer-sample\"");
237+
}
238+
if (gamesIMSample) {
239+
sampleBucketPayload.add("\"gamesim-sample\"");
240+
}
241+
if (sampleBucketPayload.length() != 0) {
242+
logger().debug("Initialize sample buckets {}", sampleBucketPayload.toString());
243+
callCouchbaseRestAPI("/sampleBuckets/install", "[" + sampleBucketPayload.toString() + "]");
244+
}
245+
}
205246

206-
StringBuilder sampleBucketPayloadBuilder = new StringBuilder();
207-
sampleBucketPayloadBuilder.append('[');
208-
if (travelSample) {
209-
sampleBucketPayloadBuilder.append("\"travel-sample\",");
210-
}
211-
if (beerSample) {
212-
sampleBucketPayloadBuilder.append("\"beer-sample\",");
213-
}
214-
if (gamesIMSample) {
215-
sampleBucketPayloadBuilder.append("\"gamesim-sample\",");
216-
}
217-
sampleBucketPayloadBuilder.append(']');
247+
private void initIndexes() throws IOException {
248+
logger().debug("Activate memory optimized index");
249+
callCouchbaseRestAPI("/settings/indexes", "indexerThreads=0&logLevel=info&maxRollbackPoints=5&storageMode=memory_optimized");
250+
}
218251

219-
callCouchbaseRestAPI(poolURL, poolPayload);
220-
callCouchbaseRestAPI(setupServicesURL, setupServiceContent);
221-
callCouchbaseRestAPI(webSettingsURL, webSettingsContent);
222-
callCouchbaseRestAPI(bucketURL, sampleBucketPayloadBuilder.toString());
252+
private String createUrlBase() {
253+
return String.format((ssl ? "https" : "http") + "://%s:%s", getContainerIpAddress(), getMappedPort(CONFIG_PORT));
254+
}
223255

224-
CouchbaseWaitStrategy s = new CouchbaseWaitStrategy();
225-
s.withBasicCredentials(clusterUsername, clusterPassword);
226-
s.waitUntilReady(this);
227-
callCouchbaseRestAPI("/settings/indexes", "indexerThreads=0&logLevel=info&maxRollbackPoints=5&storageMode=memory_optimized");
228-
} catch (Exception e) {
229-
throw new RuntimeException(e);
230-
}
256+
@NotNull
257+
private CouchbaseNodeWaitStrategy createCouchbaseWaitStrategy() {
258+
return new CouchbaseNodeWaitStrategy()
259+
.withUsername(clusterUsername)
260+
.withPassword(clusterPassword)
261+
.withSsl(ssl);
231262
}
232263

233264
public void createBucket(BucketSettings bucketSetting, boolean primaryIndex) {
265+
logger().debug("Creating bucket {}", bucketSetting.name());
234266
ClusterManager clusterManager = getCouchbaseCluster().clusterManager(clusterUsername, clusterPassword);
235267
// Insert Bucket
236268
BucketSettings bucketSettings = clusterManager.insertBucket(bucketSetting);
237269
// Insert Bucket admin user
270+
logger().debug("Creating bucket admin user '{}'", bucketSetting.name());
238271
UserSettings userSettings = UserSettings.build()
239272
.password(bucketSetting.password())
240273
.roles(Collections.singletonList(new UserRole("bucket_admin", bucketSetting.name())));
@@ -243,35 +276,38 @@ public void createBucket(BucketSettings bucketSetting, boolean primaryIndex) {
243276
} catch (Exception e) {
244277
logger().warn("Unable to insert user '" + bucketSetting.name() + "', maybe you are using older version");
245278
}
279+
this.getCouchbaseNodeWaitStrategy().waitUntilReady(this);
246280
if (index) {
247281
Bucket bucket = getCouchbaseCluster().openBucket(bucketSettings.name(), bucketSettings.password());
248282
new CouchbaseQueryServiceWaitStrategy(bucket).waitUntilReady(this);
249283
if (primaryIndex) {
284+
logger().debug("Creating primary index");
250285
bucket.query(Index.createPrimaryIndex().on(bucketSetting.name()));
251286
}
252287
}
253288
}
254289

255290
public void callCouchbaseRestAPI(String url, String payload) throws IOException {
256-
String fullUrl = urlBase + url;
291+
String fullUrl = getUrlBase() + url;
292+
@Cleanup(value = "disconnect")
257293
HttpURLConnection httpConnection = (HttpURLConnection) ((new URL(fullUrl).openConnection()));
258294
httpConnection.setDoOutput(true);
259295
httpConnection.setRequestMethod("POST");
260296
httpConnection.setRequestProperty("Content-Type",
261297
"application/x-www-form-urlencoded");
262298
String encoded = Base64.encode((clusterUsername + ":" + clusterPassword).getBytes("UTF-8"));
263299
httpConnection.setRequestProperty("Authorization", "Basic " + encoded);
300+
@Cleanup
264301
DataOutputStream out = new DataOutputStream(httpConnection.getOutputStream());
265302
out.writeBytes(payload);
266303
out.flush();
267-
out.close();
268304
httpConnection.getResponseCode();
269-
httpConnection.disconnect();
270305
}
271306

272307
@Override
273308
public void start() {
274309
super.start();
310+
init();
275311
if (!newBuckets.isEmpty()) {
276312
for (BucketSettings bucketSetting : newBuckets) {
277313
createBucket(bucketSetting, primaryIndex);
@@ -284,7 +320,6 @@ private CouchbaseCluster createCouchbaseCluster() {
284320
}
285321

286322
private DefaultCouchbaseEnvironment createCouchbaseEnvironment() {
287-
initCluster();
288323
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder()
289324
.sslEnabled(ssl);
290325
if (isSsl()) {

src/main/java/org/testcontainers/couchbase/CouchbaseWaitStrategy.java renamed to src/main/java/org/testcontainers/couchbase/CouchbaseNodeWaitStrategy.java

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
import com.couchbase.client.deps.com.fasterxml.jackson.databind.JsonNode;
1919
import com.couchbase.client.deps.com.fasterxml.jackson.databind.ObjectMapper;
20+
import lombok.AllArgsConstructor;
21+
import lombok.NoArgsConstructor;
22+
import lombok.experimental.Wither;
2023
import org.rnorth.ducttape.TimeoutException;
2124
import org.testcontainers.containers.ContainerLaunchException;
2225
import org.testcontainers.containers.GenericContainer;
@@ -29,13 +32,17 @@
2932
import java.net.URL;
3033
import java.util.concurrent.TimeUnit;
3134

35+
import static java.net.HttpURLConnection.HTTP_OK;
36+
import static lombok.AccessLevel.PRIVATE;
3237
import static org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess;
3338

3439
/**
3540
* @author ldoguin
3641
* created on 18/07/16.
3742
*/
38-
public class CouchbaseWaitStrategy extends GenericContainer.AbstractWaitStrategy {
43+
@NoArgsConstructor
44+
@AllArgsConstructor(access = PRIVATE)
45+
public class CouchbaseNodeWaitStrategy extends GenericContainer.AbstractWaitStrategy {
3946
/**
4047
* Authorization HTTP header.
4148
*/
@@ -46,35 +53,16 @@ public class CouchbaseWaitStrategy extends GenericContainer.AbstractWaitStrategy
4653
*/
4754
private static final String AUTH_BASIC = "Basic ";
4855

49-
private String path = "/pools/default/";
50-
private int statusCode = HttpURLConnection.HTTP_OK;
51-
private boolean tlsEnabled;
52-
private String username;
53-
private String password;
54-
private ObjectMapper om = new ObjectMapper();
56+
private static final String PATH = "/pools/default/";
5557

56-
/**
57-
* Indicates that the status check should use HTTPS.
58-
*
59-
* @return this
60-
*/
61-
public CouchbaseWaitStrategy usingTls() {
62-
this.tlsEnabled = true;
63-
return this;
64-
}
58+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
6559

66-
/**
67-
* Authenticate with HTTP Basic Authorization credentials.
68-
*
69-
* @param username the username
70-
* @param password the password
71-
* @return this
72-
*/
73-
public CouchbaseWaitStrategy withBasicCredentials(String username, String password) {
74-
this.username = username;
75-
this.password = password;
76-
return this;
77-
}
60+
@Wither
61+
private boolean ssl;
62+
@Wither
63+
private String username;
64+
@Wither
65+
private String password;
7866

7967
@Override
8068
protected void waitUntilReady() {
@@ -85,7 +73,7 @@ protected void waitUntilReady() {
8573
}
8674

8775
final String uri = buildLivenessUri(livenessCheckPort).toString();
88-
logger().info("Waiting for {} seconds for URL: {}", startupTimeout.getSeconds(), uri);
76+
logger().info("Waiting {} seconds for nodes to be healthy", startupTimeout.getSeconds());
8977

9078
// try to connect to the URL
9179
try {
@@ -103,16 +91,16 @@ protected void waitUntilReady() {
10391
connection.setRequestMethod("GET");
10492
connection.connect();
10593

106-
if (statusCode != connection.getResponseCode()) {
94+
if (HTTP_OK != connection.getResponseCode()) {
10795
throw new RuntimeException(String.format("HTTP response code was: %s",
10896
connection.getResponseCode()));
10997
}
11098

11199
// Specific Couchbase wait strategy to be sure the node is online and healthy
112-
JsonNode node = om.readTree(connection.getInputStream());
100+
JsonNode node = OBJECT_MAPPER.readTree(connection.getInputStream());
113101
JsonNode statusNode = node.at("/nodes/0/status");
114102
String status = statusNode.asText();
115-
if (!"healthy".equals(status)){
103+
if (!"healthy".equals(status)) {
116104
throw new RuntimeException(String.format("Couchbase Node status was: %s", status));
117105
}
118106

@@ -125,7 +113,7 @@ protected void waitUntilReady() {
125113

126114
} catch (TimeoutException e) {
127115
throw new ContainerLaunchException(String.format(
128-
"Timed out waiting for URL to be accessible (%s should return HTTP %s)", uri, statusCode));
116+
"Timeout waiting for URL to be accessible (%s should return HTTP %s)", uri, HTTP_OK));
129117
}
130118
}
131119

@@ -136,17 +124,17 @@ protected void waitUntilReady() {
136124
* @return the liveness URI
137125
*/
138126
private URI buildLivenessUri(int livenessCheckPort) {
139-
final String scheme = (tlsEnabled ? "https" : "http") + "://";
127+
final String scheme = (ssl ? "https" : "http") + "://";
140128
final String host = container.getContainerIpAddress();
141129

142130
final String portSuffix;
143-
if ((tlsEnabled && 443 == livenessCheckPort) || (!tlsEnabled && 80 == livenessCheckPort)) {
131+
if ((ssl && 443 == livenessCheckPort) || (!ssl && 80 == livenessCheckPort)) {
144132
portSuffix = "";
145133
} else {
146134
portSuffix = ":" + String.valueOf(livenessCheckPort);
147135
}
148136

149-
return URI.create(scheme + host + portSuffix + path);
137+
return URI.create(scheme + host + portSuffix + PATH);
150138
}
151139

152140
/**

0 commit comments

Comments
 (0)