Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b82a2c
Import yjshen's PR.
yjshen Aug 11, 2015
eddcc47
Use newer shaded docker-client artifact
JoshRosen Oct 19, 2015
8bb62ea
Use map for setting environment variables.
JoshRosen Oct 19, 2015
23443a5
Ensure that Docker container is cleaned up after error.
JoshRosen Oct 19, 2015
e6c7709
Remove a bunch of layers of indirection / abstraction.
JoshRosen Nov 5, 2015
d06847b
Fix networking for boot2docker.
JoshRosen Nov 5, 2015
93bcf45
Log warning in case container cleanup fails
JoshRosen Nov 5, 2015
bf98ae0
Rename class and freeze image versions
JoshRosen Nov 5, 2015
1e389e2
Automatically get docker IP from docker-machine and boot2docker.
JoshRosen Nov 5, 2015
d9c37df
Print nicer message if Docker connection fails.
JoshRosen Nov 5, 2015
95f00e1
Add test tag for excluding Docker tests in SBT.
JoshRosen Nov 5, 2015
fcf5dc4
Upgrade to non-ancient version of docker-client.
JoshRosen Nov 6, 2015
2273f87
Upgrade Jersey to avoid ASM incompatibilities / classpath ordering is…
JoshRosen Nov 6, 2015
65315c4
Merge remote-tracking branch 'origin/master' into docker-jdbc-tests
JoshRosen Nov 6, 2015
cba340f
Experiment with bumping Jersey, even though I know we can't do that.
JoshRosen Nov 6, 2015
1a09a65
Hack to fix IP address binding in Jenkins.
JoshRosen Nov 9, 2015
af84a47
Move docker tests to own subproject.
JoshRosen Nov 9, 2015
4899b2e
Add DockerTest tag.
JoshRosen Nov 9, 2015
ef85200
Use non-shaded Docker client.
JoshRosen Nov 9, 2015
6db2c1c
Fix dependency problems.
JoshRosen Nov 10, 2015
9011bc5
Merge remote-tracking branch 'origin/master' into docker-jdbc-tests
JoshRosen Nov 10, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions docker-integration-tests/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?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.spark</groupId>
<artifactId>spark-parent_2.10</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>spark-docker-integration-tests_2.10</artifactId>
<packaging>jar</packaging>
<name>Spark Project Docker Integration Tests</name>
<url>http://spark.apache.org/</url>
<properties>
<sbt.project.name>docker-integration-tests</sbt.project.name>
</properties>

<dependencies>
<dependency>
<groupId>com.spotify</groupId>
<artifactId>docker-client</artifactId>
<classifier>shaded</classifier>
<scope>test</scope>
<!--
See https://github.com/spotify/docker-client/pull/272#issuecomment-155249101
for an explanation of why these exclusions are (necessarily) a mess.
-->
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Necessary in order to avoid errors in log messages: -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-test-tags_${scala.binary.version}</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!-- Jersey dependencies, used to override version.
See https://github.com/apache/spark/pull/9503#issuecomment-154369560 for
background on why we need to use a newer Jersey only in this test module;
we can remove this once https://github.com/spotify/docker-client/pull/272 is
merged and a new docker-client release is published. -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- End Jersey dependencies -->
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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.spark.sql.jdbc

import java.net.ServerSocket
import java.sql.Connection

import scala.collection.JavaConverters._
import scala.util.control.NonFatal

import com.spotify.docker.client._
import com.spotify.docker.client.messages.{ContainerConfig, HostConfig, PortBinding}
import org.scalatest.BeforeAndAfterAll
import org.scalatest.concurrent.Eventually
import org.scalatest.time.SpanSugar._

import org.apache.spark.SparkFunSuite
import org.apache.spark.util.DockerUtils
import org.apache.spark.sql.test.SharedSQLContext

abstract class DatabaseOnDocker {
/**
* The docker image to be pulled.
*/
val imageName: String

/**
* Environment variables to set inside of the Docker container while launching it.
*/
val env: Map[String, String]

/**
* The container-internal JDBC port that the database listens on.
*/
val jdbcPort: Int

/**
* Return a JDBC URL that connects to the database running at the given IP address and port.
*/
def getJdbcUrl(ip: String, port: Int): String
}

abstract class DockerJDBCIntegrationSuite
extends SparkFunSuite
with BeforeAndAfterAll
with Eventually
with SharedSQLContext {

val db: DatabaseOnDocker

private var docker: DockerClient = _
private var containerId: String = _
protected var jdbcUrl: String = _

override def beforeAll() {
super.beforeAll()
try {
docker = DefaultDockerClient.fromEnv.build()
// Check that Docker is actually up
try {
docker.ping()
} catch {
case NonFatal(e) =>
log.error("Exception while connecting to Docker. Check whether Docker is running.")
throw e
}
// Ensure that the Docker image is installed:
try {
docker.inspectImage(db.imageName)
} catch {
case e: ImageNotFoundException =>
log.warn(s"Docker image ${db.imageName} not found; pulling image from registry")
docker.pull(db.imageName)
}
// Configure networking (necessary for boot2docker / Docker Machine)
val externalPort: Int = {
val sock = new ServerSocket(0)
val port = sock.getLocalPort
sock.close()
port
}
val dockerIp = DockerUtils.getDockerIp()
val hostConfig: HostConfig = HostConfig.builder()
.networkMode("bridge")
.portBindings(
Map(s"${db.jdbcPort}/tcp" -> List(PortBinding.of(dockerIp, externalPort)).asJava).asJava)
.build()
// Create the database container:
val config = ContainerConfig.builder()
.image(db.imageName)
.networkDisabled(false)
.env(db.env.map { case (k, v) => s"$k=$v" }.toSeq.asJava)
.hostConfig(hostConfig)
.exposedPorts(s"${db.jdbcPort}/tcp")
.build()
containerId = docker.createContainer(config).id
// Start the container and wait until the database can accept JDBC connections:
docker.startContainer(containerId)
jdbcUrl = db.getJdbcUrl(dockerIp, externalPort)
eventually(timeout(60.seconds), interval(1.seconds)) {
val conn = java.sql.DriverManager.getConnection(jdbcUrl)
conn.close()
}
// Run any setup queries:
val conn: Connection = java.sql.DriverManager.getConnection(jdbcUrl)
try {
dataPreparation(conn)
} finally {
conn.close()
}
} catch {
case NonFatal(e) =>
try {
afterAll()
} finally {
throw e
}
}
}

override def afterAll() {
try {
if (docker != null) {
try {
if (containerId != null) {
docker.killContainer(containerId)
docker.removeContainer(containerId)
}
} catch {
case NonFatal(e) =>
logWarning(s"Could not stop container $containerId", e)
} finally {
docker.close()
}
}
} finally {
super.afterAll()
}
}

/**
* Prepare databases and tables for testing.
*/
def dataPreparation(connection: Connection): Unit
}
Loading