Skip to content

Commit

Permalink
Experiments with docker API
Browse files Browse the repository at this point in the history
### What's done:
* Refactoring
* Added use for AutoCloseable resources
  • Loading branch information
petertrr committed Feb 9, 2021
1 parent ecdbdd3 commit e7c4e23
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.github.dockerjava.httpclient5.ApacheDockerHttpClient
import com.github.dockerjava.transport.DockerHttpClient
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
import org.cqfn.save.domain.RunConfiguration
import org.slf4j.LoggerFactory

import java.io.BufferedOutputStream
Expand All @@ -30,19 +31,22 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker.
/**
* Creates a docker container with [file], prepared to execute it
*
* @param runConfiguration a [RunConfiguration] for the supplied binary
* @param file an executable file
* @param resources additional files to be copied in the container too
* @return id of created container or null if it wasn't created
*/
fun createWithFile(file: File, resources: Collection<File> = emptySet()): String? {
fun createWithFile(runConfiguration: RunConfiguration,
file: File,
resources: Collection<File> = emptySet()): String? {
// ensure the image is present in the system
dockerClient.pullImageCmd("docker.io/library/ubuntu")
.withTag("latest")
.start()
.awaitCompletion()

val createContainerCmdResponse = dockerClient.createContainerCmd("ubuntu:latest")
.withCmd("./${file.name}")
.withCmd(runConfiguration.startCommand)
.withName("testContainer")
.withHostConfig(HostConfig.newHostConfig()
.withRuntime("runsc")
Expand All @@ -53,28 +57,41 @@ class ContainerManager(private val dockerHost: String = "unix:///var/run/docker.
return null
}

val out = ByteArrayOutputStream()
val buffOut = BufferedOutputStream(out)
val gzOut = GZIPOutputStream(buffOut)
val tgzOut = TarArchiveOutputStream(gzOut)
tgzOut.putArchiveEntry(TarArchiveEntry(file))
Files.copy(file.toPath(), tgzOut)
tgzOut.closeArchiveEntry()
resources.forEach {
tgzOut.putArchiveEntry(TarArchiveEntry(it))
Files.copy(it.toPath(), tgzOut)
tgzOut.closeArchiveEntry()
createTgzStream(file, *resources.toTypedArray()).use { out ->
dockerClient.copyArchiveToContainerCmd(createContainerCmdResponse.id)
.withTarInputStream(out.toByteArray().inputStream())
.withRemotePath("/run")
.exec()
}
tgzOut.finish()
gzOut.finish()
buffOut.flush()
dockerClient.copyArchiveToContainerCmd(createContainerCmdResponse.id)
.withTarInputStream(out.toByteArray().inputStream())
.withRemotePath("/run")
.exec()
return createContainerCmdResponse.id
}

/**
* Add [files] to .tar.gz archive and return the underlying [ByteArrayOutputStream]
*
* @param files files to be added to archive
* @return resulting [ByteArrayOutputStream]
*/
private fun createTgzStream(vararg files: File): ByteArrayOutputStream {
val out = ByteArrayOutputStream()
BufferedOutputStream(out).use { buffOut ->
GZIPOutputStream(buffOut).use { gzOut ->
TarArchiveOutputStream(gzOut).use { tgzOut ->
tgzOut.closeArchiveEntry()
files.forEach {
tgzOut.putArchiveEntry(TarArchiveEntry(it))
Files.copy(it.toPath(), tgzOut)
tgzOut.closeArchiveEntry()
}
tgzOut.finish()
}
gzOut.finish()
}
buffOut.flush()
}
return out
}

companion object {
private val log = LoggerFactory.getLogger(ContainerManager::class.java)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cqfn.save.backend.docker

import org.cqfn.save.domain.RunConfiguration
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
Expand Down Expand Up @@ -29,7 +30,11 @@ class ContainerManagerTest {
testFile.writeText("wow such testing")
val resourceFile = createTempFile().toFile()
resourceFile.writeText("Lorem ipsum dolor sit amet")
testContainerId = containerManager.createWithFile(testFile, listOf(resourceFile))!!
testContainerId = containerManager.createWithFile(
RunConfiguration("./script.sh", testFile.name),
testFile,
listOf(resourceFile)
)!!
val inspectContainerResponse = containerManager.dockerClient
.inspectContainerCmd(testContainerId)
.exec()
Expand Down

0 comments on commit e7c4e23

Please sign in to comment.