Skip to content

Commit ce0124a

Browse files
committed
createTar() can now handle directories and sub directories.
1 parent a7238b5 commit ce0124a

4 files changed

Lines changed: 154 additions & 35 deletions

File tree

.idea/jarRepositories.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/groovy/com/eficode/devstack/container/Container.groovy

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import de.gesellix.docker.remote.api.IdResponse
88
import de.gesellix.docker.remote.api.core.ClientException
99
import de.gesellix.docker.remote.api.core.Frame
1010
import de.gesellix.docker.remote.api.core.StreamCallback
11+
import groovy.io.FileType
1112
import org.apache.commons.compress.archivers.ArchiveEntry
1213
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
1314
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
1415
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
1516
import org.apache.commons.compress.utils.IOUtils
1617
import org.apache.commons.io.FileUtils
18+
import org.codehaus.groovy.runtime.ResourceGroovyMethods
1719
import org.slf4j.Logger
1820
import org.slf4j.LoggerFactory
1921

@@ -33,10 +35,6 @@ trait Container {
3335
abstract String createContainer()
3436

3537

36-
37-
38-
39-
4038
/**
4139
* Replaced the default docker connection (local) with a remote, secure one
4240
* @param host ex: "https://docker.domain.se:2376"
@@ -58,21 +56,19 @@ trait Container {
5856
boolean ping() {
5957
try {
6058
return dockerClient.ping().content as String == "OK"
61-
}catch(SocketException ex) {
59+
} catch (SocketException ex) {
6260
log.warn("Failed to ping Docker engine:" + ex.message)
6361
return false
6462
}
6563

6664
}
6765

6866

69-
70-
71-
boolean isCreated(){
67+
boolean isCreated() {
7268

7369
ArrayList<Map> content = dockerClient.ps().content
74-
ArrayList<String> containerNames = content.collect {it.Names}.flatten()
75-
return containerNames.find{ it == "/" + getContainerName()} != null
70+
ArrayList<String> containerNames = content.collect { it.Names }.flatten()
71+
return containerNames.find { it == "/" + getContainerName() } != null
7672

7773
}
7874

@@ -129,35 +125,64 @@ trait Container {
129125
if (dockerClient.inspectContainer(containerId).content.state.running) {
130126
log.warn("\tFailed to stop container" + containerId)
131127
return false
132-
}else {
128+
} else {
133129
log.info("\tContainer stopped")
134130
return true
135131
}
136132
}
137133

138134

135+
static File createTar(ArrayList<String> filePaths, String outputPath) {
139136

140137

141-
static File createTar(ArrayList<String> filePaths, String outputPath) {
138+
log.info("Creating tar file:" + outputPath)
139+
log.debug("\tUsing source paths:")
140+
filePaths.each {log.debug("\t\t$it")}
142141

143142

144143
File outputFile = new File(outputPath)
145-
TarArchiveOutputStream out = new TarArchiveOutputStream(Files.newOutputStream(outputFile.toPath()))
144+
TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(Files.newOutputStream(outputFile.toPath()))
146145

146+
log.info("\tProcessing files")
147147
filePaths.each { filePath ->
148+
log.debug("\t\tEvaluating:" + filePath)
149+
148150
File newEntryFile = new File(filePath)
149-
assert newEntryFile.isFile() && newEntryFile.canRead(), "Error creating TAR cant read file:" + filePath
151+
152+
assert (newEntryFile.isDirectory() || newEntryFile.isFile()) && newEntryFile.canRead(), "Error creating TAR cant read file:" + filePath
153+
log.trace("\t"*3 + "Can read file/dir")
154+
155+
if (newEntryFile.isDirectory()) {
156+
log.trace("\t"*3 + "File is actually directory, processing sub files")
157+
newEntryFile.eachFileRecurse(FileType.FILES) { subFile ->
158+
159+
String path = ResourceGroovyMethods.relativePath(newEntryFile, subFile)
160+
log.trace("\t"*4 + "Processing sub file:" + path)
161+
TarArchiveEntry entry = new TarArchiveEntry(subFile, path)
162+
entry.setSize(subFile.size())
163+
tarArchive.putArchiveEntry(entry)
164+
tarArchive.write(subFile.bytes)
165+
tarArchive.closeArchiveEntry()
166+
log.trace("\t"*5 + "Added to archive")
167+
}
168+
} else {
169+
log.trace("\t"*4 + "Processing file:" + newEntryFile.name)
170+
TarArchiveEntry entry = new TarArchiveEntry(newEntryFile, newEntryFile.name)
171+
entry.setSize(newEntryFile.size())
172+
tarArchive.putArchiveEntry(entry)
173+
tarArchive.write(newEntryFile.bytes)
174+
tarArchive.closeArchiveEntry()
175+
log.trace("\t"*5 + "Added to archive")
176+
177+
}
178+
179+
150180

151181

152-
TarArchiveEntry entry = new TarArchiveEntry(newEntryFile, newEntryFile.name)
153-
entry.setSize(newEntryFile.size())
154-
out.putArchiveEntry(entry)
155-
out.write(newEntryFile.bytes)
156182

157-
out.closeArchiveEntry()
158183
}
159184

160-
out.finish()
185+
tarArchive.finish()
161186

162187
return outputFile
163188

@@ -167,11 +192,10 @@ trait Container {
167192
static ArrayList<File> extractTar(File tarFile, String outputPath) {
168193

169194

170-
171-
log.info("Extracting: " + tarFile.path + " (${tarFile.size()/1024}kB)")
195+
log.info("Extracting: " + tarFile.path + " (${tarFile.size() / 1024}kB)")
172196
log.info("\tTo:" + outputPath)
173197
assert outputPath[-1] == "/", "outputPath must end with /"
174-
ArrayList<File>outFiles = []
198+
ArrayList<File> outFiles = []
175199
TarArchiveInputStream i = new TarArchiveInputStream(tarFile.newInputStream())
176200

177201
ArchiveEntry entry = null
@@ -184,11 +208,11 @@ trait Container {
184208

185209
if (entry.isDirectory()) {
186210
assert outFile.mkdirs(), "Error creating directory:" + outFile.path
187-
}else {
211+
} else {
188212
outFile.parentFile.mkdirs()
189213
OutputStream o = Files.newOutputStream(outFile.toPath())
190-
long output = IOUtils.copy(i,o)
191-
log.trace("\t\tExtracted ${(output/1024).round(1)}kB")
214+
long output = IOUtils.copy(i, o)
215+
log.trace("\t\tExtracted ${(output / 1024).round(1)}kB")
192216
o.close()
193217
}
194218
outFiles.add(outFile)
@@ -231,9 +255,6 @@ trait Container {
231255
}
232256

233257

234-
235-
236-
237258
static class ContainerCallback<T> implements StreamCallback<T> {
238259

239260
ArrayList<String> output = []
@@ -242,25 +263,23 @@ trait Container {
242263
void onNext(Object o) {
243264
if (o instanceof Frame) {
244265
output.add(o.payloadAsString)
245-
}else {
266+
} else {
246267
output.add(o.toString())
247268
}
248269

249270
}
250271
}
251272

252273

253-
ArrayList<String> runBashCommandInContainer(String command, long timeoutS=10) {
274+
ArrayList<String> runBashCommandInContainer(String command, long timeoutS = 10) {
254275

255276

256277
ContainerCallback callBack = new ContainerCallback()
257-
EngineResponse<IdResponse> response = dockerClient.exec(containerId, ["/bin/bash", "-c", command],callBack , Duration.ofSeconds(timeoutS))
258-
278+
EngineResponse<IdResponse> response = dockerClient.exec(containerId, ["/bin/bash", "-c", command], callBack, Duration.ofSeconds(timeoutS))
259279

260280

261281
return callBack.output
262282
}
263283

264284

265-
266285
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.eficode.devstack.container
2+
3+
import groovy.io.FileType
4+
import org.slf4j.Logger
5+
import org.slf4j.LoggerFactory
6+
import spock.lang.Specification
7+
8+
import java.nio.file.Files
9+
import java.nio.file.Path
10+
11+
class ContainerTest extends Specification {
12+
13+
static Logger log = LoggerFactory.getLogger(ContainerTest.class)
14+
15+
16+
17+
class ContainerImpl implements Container {
18+
19+
String containerName = "spoc"
20+
String containerMainPort = "666"
21+
22+
String createContainer() {}
23+
}
24+
25+
26+
def testCreateTar() {
27+
28+
setup:
29+
File tarOutDir = File.createTempDir("tarOut")
30+
File tarSourceDir = File.createTempDir("tarSourceDir")
31+
File tarSourceSubDir = new File(tarSourceDir.path + "/subDir")
32+
assert tarSourceSubDir.mkdir()
33+
34+
ArrayList<File> tarSourceRootFiles = []
35+
ArrayList<File> tarSourceSubFiles = []
36+
(0..9).each { i ->
37+
38+
39+
File newRootFile = new File(tarSourceDir.absolutePath + "/tarRootFile${i}.txt")
40+
newRootFile.createNewFile()
41+
newRootFile.write("SPOC content for root file index: $i")
42+
tarSourceRootFiles.add(newRootFile)
43+
44+
45+
File newSubFile = new File(tarSourceSubDir.absolutePath + "/tarSubFile${i}.txt")
46+
newSubFile.createNewFile()
47+
newSubFile.write("SPOC content for sub file index: $i")
48+
tarSourceSubFiles.add(newSubFile)
49+
50+
51+
}
52+
53+
log.info("\tCreated test files and directories:")
54+
log.info("\t\tTar root directory:" + tarSourceDir.absolutePath)
55+
log.info("\t\tTar sub directory:" + tarSourceSubDir.absolutePath)
56+
log.info("\t\tTar out directory:" + tarOutDir.absolutePath)
57+
log.info("\t\tTar root files:" + tarSourceRootFiles.name.join(","))
58+
log.info("\t\tTar sub files:" + tarSourceSubFiles.name.join(","))
59+
60+
when:
61+
File tarFile = ContainerImpl.createTar([tarSourceDir.absolutePath],tarOutDir.absolutePath + "/tarFile.tar" )
62+
63+
then:
64+
tarOutDir.exists()
65+
66+
when:
67+
ArrayList<File> extractedFiles = ContainerImpl.extractTar(tarFile, tarOutDir.absolutePath + "/")
68+
ArrayList<File> allSourceFiles = tarSourceRootFiles + tarSourceSubFiles
69+
70+
then:
71+
tarOutDir.eachFileRecurse(FileType.FILES) {extractedFile ->
72+
73+
if (extractedFile.name != tarFile.name ) {
74+
File matchingSourceFile = allSourceFiles.find {it.name == extractedFile.name}
75+
76+
assert matchingSourceFile : "Could not find matching source file, for file found in tar:" + extractedFile.name
77+
assert matchingSourceFile.text == extractedFile.text
78+
assert matchingSourceFile.relativePath(tarSourceDir) == extractedFile.relativePath(tarOutDir)
79+
80+
}
81+
82+
}
83+
84+
85+
86+
cleanup:
87+
tarSourceDir.deleteDir() ?: log.error("Error deleting temp files:" + tarSourceDir.absolutePath)
88+
tarOutDir.deleteDir() ?: log.error("Error deleting temp files:" + tarOutDir.absolutePath)
89+
90+
}
91+
92+
93+
94+
95+
}

src/test/groovy/com/eficode/devstack/container/impl/JsmContainerTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class JsmContainerTest extends Specification {
2626

2727

2828
@Shared
29-
String dockerRemoteHost = "https://docker.domain.com:2376"
29+
String dockerRemoteHost = "https://docker.domain.se:2376"
3030
@Shared
3131
String dockerCertPath = "resources/dockerCert"
3232

0 commit comments

Comments
 (0)