You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@bookkeeper.apache.org by GitBox <gi...@apache.org> on 2018/01/17 10:29:29 UTC

[GitHub] ivankelly closed pull request #974: Utilities for working with Arquillian and Docker

ivankelly closed pull request #974: Utilities for working with Arquillian and Docker
URL: https://github.com/apache/bookkeeper/pull/974
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/tests/integration-tests-utils/pom.xml b/tests/integration-tests-utils/pom.xml
new file mode 100644
index 000000000..3593ec507
--- /dev/null
+++ b/tests/integration-tests-utils/pom.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="
+  http://maven.apache.org/POM/4.0.0
+  http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.bookkeeper.tests</groupId>
+    <artifactId>tests-parent</artifactId>
+    <version>4.7.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.apache.bookkeeper.tests</groupId>
+  <artifactId>integration-tests-utils</artifactId>
+  <packaging>jar</packaging>
+
+  <name>Apache BookKeeper :: Tests :: Utility module for Arquillian based integration tests</name>
+
+  <properties>
+    <arquillian-cube.version>1.13.0</arquillian-cube.version>
+    <commons-compress.version>1.15</commons-compress.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-compress</artifactId>
+      <version>${commons-compress.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.zookeeper</groupId>
+      <artifactId>zookeeper</artifactId>
+      <version>${zookeeper.version}</version>
+      <scope>compile</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>net.java.dev.javacc</groupId>
+          <artifactId>javacc</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-log4j12</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>log4j</groupId>
+          <artifactId>log4j</artifactId>
+	</exclusion>
+        <exclusion>
+          <groupId>io.netty</groupId>
+          <artifactId>netty</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.arquillian.cube</groupId>
+      <artifactId>arquillian-cube-docker</artifactId>
+      <version>${arquillian-cube.version}</version>
+    </dependency>
+
+  </dependencies>
+</project>
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperClusterUtils.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperClusterUtils.java
new file mode 100644
index 000000000..d70d543e9
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperClusterUtils.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tests;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.github.dockerjava.api.DockerClient;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.net.Socket;
+
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BookKeeperClusterUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(BookKeeperClusterUtils.class);
+
+    public static String zookeeperConnectString(DockerClient docker) {
+        return DockerUtils.cubeIdsMatching("zookeeper").stream()
+            .map((id) -> DockerUtils.getContainerIP(docker, id)).collect(Collectors.joining(":"));
+    }
+
+    public static ZooKeeper zookeeperClient(DockerClient docker) throws Exception {
+        String connectString = BookKeeperClusterUtils.zookeeperConnectString(docker);
+        CompletableFuture<Void> future = new CompletableFuture<>();
+        ZooKeeper zk = new ZooKeeper(connectString, 10000,
+                                     (e) -> {
+                                         if (e.getState().equals(KeeperState.SyncConnected)) {
+                                             future.complete(null);
+                                         }
+                                     });
+        future.get();
+        return zk;
+    }
+
+    public static boolean zookeeperRunning(DockerClient docker, String containerId) {
+        String ip = DockerUtils.getContainerIP(docker, containerId);
+        try (Socket socket = new Socket(ip, 2181)) {
+            socket.setSoTimeout(1000);
+            socket.getOutputStream().write("ruok".getBytes(UTF_8));
+            byte[] resp = new byte[4];
+            if (socket.getInputStream().read(resp) == 4) {
+                return new String(resp, UTF_8).equals("imok");
+            }
+        } catch (IOException e) {
+            // ignore, we'll return fallthrough to return false
+        }
+        return false;
+    }
+
+    public static void legacyMetadataFormat(DockerClient docker) throws Exception {
+        try (ZooKeeper zk = BookKeeperClusterUtils.zookeeperClient(docker)) {
+            zk.create("/ledgers", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+            zk.create("/ledgers/available", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+        }
+    }
+
+    private static boolean waitBookieState(DockerClient docker, String containerId,
+                                           int timeout, TimeUnit timeoutUnit,
+                                           boolean upOrDown) {
+        long timeoutMillis = timeoutUnit.toMillis(timeout);
+        long pollMillis = 1000;
+        String bookieId = DockerUtils.getContainerIP(docker, containerId) + ":3181";
+        try (ZooKeeper zk = BookKeeperClusterUtils.zookeeperClient(docker)) {
+            String path = "/ledgers/available/" + bookieId;
+            while (timeoutMillis > 0) {
+                if ((zk.exists(path, false) != null) == upOrDown) {
+                    return true;
+                }
+                Thread.sleep(pollMillis);
+                timeoutMillis -= pollMillis;
+            }
+        } catch (Exception e) {
+            LOG.error("Exception checking for bookie state", e);
+            return false;
+        }
+        LOG.warn("Bookie {} didn't go {} after {} seconds",
+                 containerId, upOrDown ? "up" : "down",
+                 timeoutUnit.toSeconds(timeout));
+        return false;
+    }
+
+    public static boolean waitBookieUp(DockerClient docker, String containerId,
+                                       int timeout, TimeUnit timeoutUnit) {
+        return waitBookieState(docker, containerId, timeout, timeoutUnit, true);
+    }
+
+    public static boolean waitBookieDown(DockerClient docker, String containerId,
+                                         int timeout, TimeUnit timeoutUnit) {
+        return waitBookieState(docker, containerId, timeout, timeoutUnit, false);
+    }
+
+    public static boolean startBookieWithVersion(DockerClient docker, String containerId, String version) {
+        try {
+            DockerUtils.runCommand(docker, containerId, "supervisorctl", "start", "bookkeeper-" + version);
+        } catch (Exception e) {
+            LOG.error("Exception starting bookie", e);
+            return false;
+        }
+        return waitBookieUp(docker, containerId, 10, TimeUnit.SECONDS);
+    }
+
+    private static boolean allTrue(boolean accumulator, boolean result) {
+        return accumulator && result;
+    }
+
+    public static boolean startAllBookiesWithVersion(DockerClient docker, String version)
+            throws Exception {
+        return DockerUtils.cubeIdsMatching("bookkeeper").stream()
+            .map((b) -> startBookieWithVersion(docker, b, version))
+            .reduce(true, BookKeeperClusterUtils::allTrue);
+    }
+
+    public static boolean stopBookie(DockerClient docker, String containerId) {
+        try {
+            DockerUtils.runCommand(docker, containerId, "supervisorctl", "stop", "all");
+        } catch (Exception e) {
+            LOG.error("Exception stopping bookie", e);
+            return false;
+        }
+        return waitBookieDown(docker, containerId, 10, TimeUnit.SECONDS);
+    }
+
+    public static boolean stopAllBookies(DockerClient docker) {
+        return DockerUtils.cubeIdsMatching("bookkeeper").stream()
+            .map((b) -> stopBookie(docker, b))
+            .reduce(true, BookKeeperClusterUtils::allTrue);
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperLogsToTargetDirStopAction.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperLogsToTargetDirStopAction.java
new file mode 100644
index 000000000..cab00f8c1
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/BookKeeperLogsToTargetDirStopAction.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tests;
+
+import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
+import org.arquillian.cube.impl.model.CubeId;
+import org.arquillian.cube.spi.beforeStop.BeforeStopAction;
+
+public class BookKeeperLogsToTargetDirStopAction implements BeforeStopAction {
+    private DockerClientExecutor dockerClientExecutor;
+    private CubeId containerID;
+
+    public void setDockerClientExecutor(DockerClientExecutor executor) {
+        this.dockerClientExecutor = executor;
+    }
+
+    public void setContainerID(CubeId containerID) {
+        this.containerID = containerID;
+    }
+
+    @Override
+    public void doBeforeStop() {
+        DockerUtils.dumpContainerLogToTarget(dockerClientExecutor.getDockerClient(), containerID.getId());
+        DockerUtils.dumpContainerLogDirToTarget(dockerClientExecutor.getDockerClient(),
+                                                containerID.getId(), "/var/log/bookkeeper");
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/DockerUtils.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/DockerUtils.java
new file mode 100644
index 000000000..7d183a184
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/DockerUtils.java
@@ -0,0 +1,170 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tests;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.async.ResultCallback;
+import com.github.dockerjava.api.model.Frame;
+import com.github.dockerjava.api.model.ContainerNetwork;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DockerUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(DockerUtils.class);
+
+    private static File getTargetDirectory(String containerId) {
+        String base = System.getProperty("maven.buildDirectory");
+        if (base == null) {
+            base = "target";
+        }
+        File directory = new File(base + "/container-logs/" + containerId);
+        if (!directory.exists() && !directory.mkdirs()) {
+            LOG.error("Error creating directory for container logs.");
+        }
+        return directory;
+    }
+
+    public static void dumpContainerLogToTarget(DockerClient docker, String containerId) {
+        File output = new File(getTargetDirectory(containerId), "docker.log");
+        try (FileOutputStream os = new FileOutputStream(output)) {
+            CompletableFuture<Boolean> future = new CompletableFuture<>();
+            docker.logContainerCmd(containerId).withStdOut(true)
+                .withStdErr(true).withTimestamps(true).exec(new ResultCallback<Frame>() {
+                        @Override
+                        public void close() {}
+
+                        @Override
+                        public void onStart(Closeable closeable) {}
+
+                        @Override
+                        public void onNext(Frame object) {
+                            try {
+                                os.write(object.getPayload());
+                            } catch (IOException e) {
+                                onError(e);
+                            }
+                        }
+
+                        @Override
+                        public void onError(Throwable throwable) {
+                            future.completeExceptionally(throwable);
+                        }
+
+                        @Override
+                        public void onComplete() {
+                            future.complete(true);
+                        }
+                    });
+            future.get();
+        } catch (ExecutionException|IOException e) {
+            LOG.error("Error dumping log for {}", containerId, e);
+        } catch (InterruptedException ie) {
+            Thread.currentThread().interrupt();
+            LOG.info("Interrupted dumping log from container {}", containerId, ie);
+        }
+    }
+
+    public static void dumpContainerLogDirToTarget(DockerClient docker, String containerId, String path) {
+        final int READ_BLOCK_SIZE = 10000;
+
+        try (InputStream dockerStream = docker.copyArchiveFromContainerCmd(containerId, path).exec();
+             TarArchiveInputStream stream = new TarArchiveInputStream(dockerStream)) {
+            TarArchiveEntry entry = stream.getNextTarEntry();
+            while (entry != null) {
+                if (entry.isFile()) {
+                    File output = new File(getTargetDirectory(containerId), entry.getName().replace("/", "-"));
+                    try (FileOutputStream os = new FileOutputStream(output)) {
+                        byte[] block = new byte[READ_BLOCK_SIZE];
+                        int read = stream.read(block, 0, READ_BLOCK_SIZE);
+                        while (read > -1) {
+                            os.write(block, 0, read);
+                            read = stream.read(block, 0, READ_BLOCK_SIZE);
+                        }
+                    }
+                }
+                entry = stream.getNextTarEntry();
+            }
+        } catch (IOException e) {
+            LOG.error("Error reading bk logs from container {}", containerId, e);
+        }
+    }
+
+    public static String getContainerIP(DockerClient docker, String containerId) {
+        for (Map.Entry<String, ContainerNetwork> e : docker.inspectContainerCmd(containerId)
+                 .exec().getNetworkSettings().getNetworks().entrySet()) {
+            return e.getValue().getIpAddress();
+        }
+        throw new IllegalArgumentException("Container " + containerId + " has no networks");
+    }
+
+    public static void runCommand(DockerClient docker, String containerId, String... cmd) throws Exception {
+        CompletableFuture<Boolean> future = new CompletableFuture<>();
+        String execid = docker.execCreateCmd(containerId).withCmd(cmd).exec().getId();
+        docker.execStartCmd(execid).withDetach(false).exec(new ResultCallback<Frame>() {
+                @Override
+                public void close() {}
+
+                @Override
+                public void onStart(Closeable closeable) {
+                }
+
+                @Override
+                public void onNext(Frame object) {
+                    LOG.info("DOCKER.exec({}): {}", cmd, object);
+                }
+
+                @Override
+                public void onError(Throwable throwable) {
+                    future.completeExceptionally(throwable);
+                }
+
+                @Override
+                public void onComplete() {
+                    future.complete(true);
+                }
+            });
+        future.get();
+    }
+
+    public static Set<String> cubeIdsMatching(String needle) {
+        Pattern pattern = Pattern.compile("^arq.cube.docker.([^.]*).ip$");
+        return System.getProperties().keySet().stream()
+            .map(k -> pattern.matcher(k.toString()))
+            .filter(m -> m.matches())
+            .map(m -> m.group(1))
+            .filter(m -> m.contains(needle))
+            .collect(Collectors.toSet());
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/LogToTargetDirStopAction.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/LogToTargetDirStopAction.java
new file mode 100644
index 000000000..24f97615f
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/LogToTargetDirStopAction.java
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bookkeeper.tests;
+
+import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
+import org.arquillian.cube.impl.model.CubeId;
+import org.arquillian.cube.spi.beforeStop.BeforeStopAction;
+
+public class LogToTargetDirStopAction implements BeforeStopAction {
+    private DockerClientExecutor dockerClientExecutor;
+    private CubeId containerID;
+
+    public void setDockerClientExecutor(DockerClientExecutor executor) {
+        this.dockerClientExecutor = executor;
+    }
+
+    public void setContainerID(CubeId containerID) {
+        this.containerID = containerID;
+    }
+
+    @Override
+    public void doBeforeStop() {
+        DockerUtils.dumpContainerLogToTarget(dockerClientExecutor.getDockerClient(), containerID.getId());
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/NoopAwaitStrategy.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/NoopAwaitStrategy.java
new file mode 100644
index 000000000..6df8167be
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/NoopAwaitStrategy.java
@@ -0,0 +1,30 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.bookkeeper.tests;
+
+import org.arquillian.cube.spi.await.AwaitStrategy;
+
+public class NoopAwaitStrategy implements AwaitStrategy {
+    @Override
+    public boolean await() {
+        return true;
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/ZooKeeperAwaitStrategy.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/ZooKeeperAwaitStrategy.java
new file mode 100644
index 000000000..86d2d699c
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/ZooKeeperAwaitStrategy.java
@@ -0,0 +1,57 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.bookkeeper.tests;
+
+import java.util.concurrent.TimeUnit;
+
+import org.arquillian.cube.spi.Cube;
+import org.arquillian.cube.spi.await.AwaitStrategy;
+import org.arquillian.cube.spi.metadata.HasPortBindings;
+import org.arquillian.cube.docker.impl.client.config.Await;
+import org.arquillian.cube.docker.impl.docker.DockerClientExecutor;
+import org.arquillian.cube.docker.impl.util.Ping;
+import org.arquillian.cube.docker.impl.util.PingCommand;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ZooKeeperAwaitStrategy implements AwaitStrategy {
+    private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperAwaitStrategy.class);
+
+    private static final int DEFAULT_POLL_ITERATIONS = 10;
+    private static final int DEFAULT_SLEEP_TIME = 1;
+    private static final TimeUnit DEFAULT_SLEEP_TIMEUNIT = TimeUnit.SECONDS;
+
+    private Cube<?> cube;
+    private DockerClientExecutor dockerClientExecutor;
+
+    @Override
+    public boolean await() {
+        return Ping.ping(DEFAULT_POLL_ITERATIONS, DEFAULT_SLEEP_TIME, DEFAULT_SLEEP_TIMEUNIT,
+                new PingCommand() {
+                    @Override
+                    public boolean call() {
+                        return BookKeeperClusterUtils.zookeeperRunning(dockerClientExecutor.getDockerClient(),
+                                                                       cube.getId());
+                    }
+                });
+    }
+}
diff --git a/tests/integration-tests-utils/src/main/resources/log4j.properties b/tests/integration-tests-utils/src/main/resources/log4j.properties
new file mode 100644
index 000000000..09ac2e75d
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/resources/log4j.properties
@@ -0,0 +1,37 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+
+# Format is "<default threshold> (, <appender>)+
+
+# DEFAULT: console appender only, level INFO
+log4j.rootLogger=INFO,CONSOLE
+
+#
+# Log INFO level and above messages to the console
+#
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} - %-5p - [%t:%C{1}@%L] - %m%n
+
+#disable zookeeper logging
+log4j.logger.org.apache.zookeeper=OFF
+log4j.logger.org.apache.bookkeeper.bookie=INFO
+log4j.logger.org.apache.bookkeeper.meta=INFO
diff --git a/tests/pom.xml b/tests/pom.xml
index 2bc561d4b..f817001ac 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -36,6 +36,7 @@
     <module>bookkeeper-server-shaded-test</module>
     <module>bookkeeper-server-tests-shaded-test</module>
     <module>docker-all-versions-image</module>
+    <module>integration-tests-utils</module>
   </modules>
   <build>
     <plugins>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services