Skip to content

Commit 9e12884

Browse files
authored
2.3.21-SNAPSHOT (#42)
* DirectorySyncer.groovy * Now returns existing matching DirectorySyncer-container if it exists. Intended to stop creation of duplicates * Bumped to 2.3.20 * Container.groovy * Switched IOUtils package pom.xml * Bumped commons-compress to 1.26.0 to work better with dockerclient lib * 1.26.1 appears to have a bug when extracting * ImageSummaryDS.groovy * Initial commit of file * ImageSummaryDS.groovy * Before updating replaceDockerUser to use prependStartupScript * ImageSummaryDS.groovy/replaceDockerUser() * Tried to switch to changing permissions on container boot, but that would mean that container has to start always start as root and then drop to other user, this grew to complex, among other things PATH/ENVs is then no longer inherited. * AbstractContainer.groovy * A helper class intended to let you create arbitrary containers AllureContainer.groovy * WIP JsmDevDeployment.groovy * A deployment for users who wish to develop for JSM JsmContainer.groovy * Fixed bug in isAppAppUploadEnabled() Container.groovy * Added new field "user" for setting docker user on creation * Helper methods for env * prepareCustomEnvVar, hasEnv DockerClientDS.groovy * Added simplified build command build() ImageSummaryDS.groovy * Improvements to replaceDockerUser() * ImageSummaryDS.groovy * Cleanup pom.xml * Bumped to 2.3.21-SNAPSHOT
1 parent 279be1b commit 9e12884

File tree

9 files changed

+775
-24
lines changed

9 files changed

+775
-24
lines changed

pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.eficode</groupId>
88
<artifactId>devstack</artifactId>
9-
<version>2.3.20</version>
9+
<version>2.3.21-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<name>DevStack</name>
@@ -87,7 +87,7 @@
8787
<dependency>
8888
<groupId>org.apache.commons</groupId>
8989
<artifactId>commons-compress</artifactId>
90-
<version>1.21</version>
90+
<version>1.26.0</version>
9191
</dependency>
9292
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
9393
<dependency>

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

+39-15
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import org.apache.commons.compress.archivers.ArchiveEntry
2727
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
2828
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
2929
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
30-
import org.apache.commons.compress.utils.IOUtils
30+
import org.apache.commons.io.IOUtils
3131
import org.apache.commons.io.FileUtils
3232
import org.codehaus.groovy.runtime.ResourceGroovyMethods
3333
import org.slf4j.Logger
@@ -51,6 +51,7 @@ trait Container {
5151
abstract String containerImageTag
5252
ArrayList<String> containerDefaultNetworks = ["bridge"]
5353
ArrayList<String> customEnvVar = []
54+
String user = null //The user name (or UID) and optionally the user group (or GID) to use as the default user
5455

5556
String defaultShell = "/bin/bash"
5657
String containerId
@@ -148,7 +149,7 @@ trait Container {
148149

149150
/**
150151
* This capability will be added to containers when they are being created
151-
* @param capability, ex: SYS_ADMIN
152+
* @param capability , ex: SYS_ADMIN
152153
*/
153154
void prepareCapability(String capability) {
154155

@@ -177,6 +178,39 @@ trait Container {
177178
}
178179

179180

181+
/**
182+
* Prepare custom environmental variables. Must be set before creating container
183+
* @param keyVar Ex: ["key=value", "PATH=/user/local/sbin"]
184+
*/
185+
void prepareCustomEnvVar(ArrayList<String> keyVar) {
186+
187+
if (!created) {
188+
self.customEnvVar.addAll(keyVar.collect { it.toString() })
189+
} else if (!keyVar.every { hasEnv(it) }) {
190+
throw new InputMismatchException("Error, cant set new custom environment variables after creating container")
191+
}
192+
193+
}
194+
195+
/**
196+
* Checks if container has been created, and has an environmental var applied
197+
* @param envKeyValue , ex "PATH=/user/local/sbin"
198+
* @return true if present
199+
*/
200+
boolean hasEnv(String envKeyValue) {
201+
202+
if (!created) {
203+
return false
204+
}
205+
206+
List<String> envs = inspectContainer()?.getConfig()?.env
207+
Boolean present = envs?.toString()?.contains(envKeyValue) ?: false
208+
return present
209+
210+
211+
}
212+
213+
180214
/**
181215
* Get MountPoints currently attached to container
182216
* @return
@@ -197,6 +231,9 @@ trait Container {
197231
c.exposedPorts = [(self.containerMainPort + "/tcp"): [:]]
198232
}
199233

234+
if (self.user) {
235+
c.user = self.user
236+
}
200237

201238
c.hostConfig = new HostConfig().tap { h ->
202239
if (self.containerMainPort) {
@@ -872,8 +909,6 @@ trait Container {
872909
}
873910
}
874911

875-
876-
//Format is one of: `user`, `user:group`, `uid`, or `uid:gid`
877912
ArrayList<String> runCommandInContainer(String containerId, ArrayList<String> commands, long timeoutS = 10, String userGroup = null, String workingDir = null) {
878913

879914
log.info("Executing bash command in container:")
@@ -1051,17 +1086,6 @@ trait Container {
10511086
return out
10521087
}
10531088

1054-
/**
1055-
* Prepare custom environmental variables. Must be set before creating container
1056-
* @param keyVar Ex: ["key=value", "PATH=/user/local/sbin"]
1057-
*/
1058-
void prepareCustomEnvVar(ArrayList<String> keyVar) {
1059-
1060-
assert hasNeverBeenStarted(): "Error, cant set custom environment variables after creating container"
1061-
1062-
self.customEnvVar.addAll(keyVar.collect {it.toString()})
1063-
}
1064-
10651089

10661090
ArrayList<String> getContainerLogs() {
10671091

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.eficode.devstack.container.impl
2+
3+
import com.eficode.devstack.container.Container
4+
5+
/**
6+
* A helper class intended to let you create arbitrary containers quickly
7+
*/
8+
class AbstractContainer implements Container {
9+
10+
String containerName
11+
String containerMainPort = null
12+
String containerImage
13+
String containerImageTag
14+
String defaultShell
15+
16+
17+
AbstractContainer(String containerName, String containerMainPort, String containerImage, String containerImageTag, String defaultShell) {
18+
this.containerName = containerName
19+
this.containerMainPort = containerMainPort
20+
this.containerImage = containerImage
21+
this.containerImageTag = containerImageTag
22+
this.defaultShell = defaultShell
23+
}
24+
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.eficode.devstack.container.impl
2+
3+
import com.eficode.devstack.container.Container
4+
import de.gesellix.docker.remote.api.ContainerCreateRequest
5+
6+
class AllureContainer implements Container {
7+
8+
String containerName = "Alpine"
9+
String containerMainPort = "5050"
10+
String containerImage = "frankescobar/allure-docker-service"
11+
String containerImageTag = "latest"
12+
String defaultShell = "/bin/bash"
13+
String user = "2001:2001"
14+
15+
16+
AllureContainer(String dockerHost = "", String dockerCertPath = "") {
17+
if (dockerHost && dockerCertPath) {
18+
assert setupSecureRemoteConnection(dockerHost, dockerCertPath): "Error setting up secure remote docker connection"
19+
}
20+
}
21+
22+
23+
}

src/main/groovy/com/eficode/devstack/container/impl/JsmContainer.groovy

+2-7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class JsmContainer implements Container {
5353
log.info("Enabling upload of Custom JIRA Apps")
5454
if (appAppUploadEnabled) {
5555
log.debug("\tApp upload is already enabled")
56+
return
5657
}
5758
assert !created: "Error, cant enable App Upload for a container that has already been created"
5859
jvmSupportRecommendedArgs += ["-Dupm.plugin.upload.enabled=true"]
@@ -63,12 +64,7 @@ class JsmContainer implements Container {
6364
* @return
6465
*/
6566
boolean isAppAppUploadEnabled() {
66-
67-
if (!created) {
68-
return false
69-
}
70-
return inspectContainer()?.getConfig()?.env?.toString()?.contains("-Dupm.plugin.upload.enabled=true") ?: false
71-
67+
hasEnv("-Dupm.plugin.upload.enabled=true")
7268
}
7369

7470
/**
@@ -140,7 +136,6 @@ class JsmContainer implements Container {
140136
}
141137

142138

143-
144139
return containerCreateRequest
145140

146141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package com.eficode.devstack.deployment.impl
2+
3+
import com.eficode.devstack.container.Container
4+
import com.eficode.devstack.container.impl.AllureContainer
5+
import com.eficode.devstack.container.impl.JsmContainer
6+
import com.eficode.devstack.deployment.Deployment
7+
import com.eficode.devstack.util.DirectorySyncer
8+
import com.eficode.devstack.util.DockerClientDS
9+
import de.gesellix.docker.client.DockerClient
10+
import de.gesellix.docker.client.EngineResponseContent
11+
import de.gesellix.docker.remote.api.Volume
12+
import org.slf4j.Logger
13+
import org.slf4j.LoggerFactory
14+
15+
16+
class JsmDevDeployment implements Deployment {
17+
18+
Logger log = LoggerFactory.getLogger(this.class)
19+
String friendlyName = "JSM Development Platform"
20+
String deploymentNetworkName = "jsmdev"
21+
ArrayList<Deployment> subDeployments = []
22+
23+
DirectorySyncer srcSyncer
24+
ArrayList<String> srcCodePaths
25+
Volume srcCodeVolume
26+
27+
AllureContainer allureContainer
28+
Volume allureReportVolume
29+
30+
DockerClientDS dockerClient
31+
32+
//Used when naming various Docker components
33+
String componentsPrefix
34+
35+
JsmDevDeployment(String jiraBaseUrl, String dockerHost, String dockerCertPath, ArrayList<String> srcCodePaths) {
36+
37+
componentsPrefix = AllureContainer.extractDomainFromUrl(jiraBaseUrl)
38+
39+
allureContainer = new AllureContainer(dockerHost, dockerCertPath)
40+
allureContainer.containerName = componentsPrefix + "-reporter"
41+
dockerClient = allureContainer.dockerClient
42+
43+
allureReportVolume = getOrCreateVolume( componentsPrefix+ "-reports")
44+
allureContainer.prepareCustomEnvVar(["CHECK_RESULTS_EVERY_SECONDS=3", "KEEP_HISTORY=1", "KEEP_HISTORY_LATEST=30"])
45+
allureContainer.prepareVolumeMount(allureReportVolume.name, "/app/allure-results", false)
46+
47+
48+
srcCodeVolume = getOrCreateVolume(componentsPrefix + "-code")
49+
this.srcCodePaths = srcCodePaths
50+
51+
subDeployments.add(new JsmH2Deployment(jiraBaseUrl, dockerHost, dockerCertPath))
52+
jsmDeployment.jsmContainer.prepareVolumeMount(srcCodeVolume.name, "/var/atlassian/application-data/jira/scripts/", false)
53+
jsmDeployment.jsmContainer.prepareVolumeMount(allureReportVolume.name, "/var/atlassian/application-data/jira/allure-results/", false)
54+
55+
56+
}
57+
58+
JsmH2Deployment getJsmDeployment() {
59+
return subDeployments.find { it instanceof JsmH2Deployment } as JsmH2Deployment
60+
}
61+
62+
JsmContainer getJsmContainer() {
63+
return jsmDeployment.jsmContainer
64+
}
65+
66+
67+
@Override
68+
ArrayList<Container> getContainers() {
69+
return [srcSyncer, allureContainer, jsmContainer]
70+
}
71+
72+
@Override
73+
void setContainers(ArrayList<Container> containers) {
74+
throw new InputMismatchException("Not implemented")
75+
}
76+
77+
Volume getOrCreateVolume(String volumeName) {
78+
Volume volume = dockerClient.getVolumesWithName(volumeName).find { true }
79+
80+
if (volume) {
81+
log.debug("\tFound existing volume:" + volume.name)
82+
} else {
83+
log.debug("\tCreating new volume $volumeName")
84+
EngineResponseContent<Volume> volumeResponse = dockerClient.createVolume(volumeName)
85+
volume = volumeResponse?.content
86+
assert volume: "Error creating volume $volumeName, " + volumeResponse?.getStatus()?.text
87+
log.debug("\t\tCreated volume:" + volume.name)
88+
}
89+
90+
return volume
91+
}
92+
93+
@Override
94+
boolean setupDeployment() {
95+
96+
97+
srcSyncer = DirectorySyncer.createSyncToVolume(srcCodePaths, srcCodeVolume.name, "-avh --chown=2001:2001")
98+
allureContainer.created ?: allureContainer.createContainer()
99+
allureContainer.startContainer()
100+
101+
jsmDeployment.setupDeployment(true, false)
102+
103+
104+
}
105+
106+
public static class Builder {
107+
108+
private String jsmLicense
109+
private String jsmBaseUrl
110+
private String jsmVersion = "latest"
111+
private String jsmJvmDebugPort = "5005"
112+
private Boolean enableJsmDooD = false
113+
114+
private Map<String, String> appsToInstall = [:]
115+
116+
private String dockerHost
117+
private String dockerCertPath
118+
119+
private ArrayList<String> srcCodePaths
120+
121+
Builder(String baseUrl, String jsmLicense, ArrayList<String> srcCodePaths) {
122+
this.jsmLicense = jsmLicense
123+
this.jsmBaseUrl = baseUrl
124+
this.srcCodePaths = srcCodePaths
125+
}
126+
127+
Builder setJsmVersion(String version) {
128+
this.jsmVersion = version
129+
return this
130+
}
131+
132+
Builder setJsmJvmDebugPort(String port) {
133+
this.jsmJvmDebugPort = port
134+
return this
135+
}
136+
137+
/**
138+
* Enable Docker Outside of Docker by mounting "/var/run/docker.sock" in to jsm container
139+
* @return
140+
*/
141+
Builder enableJsmDood() {
142+
this.enableJsmDooD = true
143+
return this
144+
}
145+
146+
147+
Builder addAppToInstall(String appUrl, String appLicense = "") {
148+
this.appsToInstall.put(appUrl, appLicense)
149+
return this
150+
}
151+
152+
Builder setDockerHost(String host) {
153+
this.dockerHost = host
154+
return this
155+
}
156+
157+
Builder setDockerCertPath(String certPath) {
158+
this.dockerCertPath = certPath
159+
return this
160+
}
161+
162+
163+
JsmDevDeployment build() {
164+
165+
JsmDevDeployment devDeployment = new JsmDevDeployment(jsmBaseUrl, dockerHost, dockerCertPath, srcCodePaths)
166+
167+
devDeployment.jsmDeployment.jsmContainer.containerImageTag = this.jsmVersion
168+
devDeployment.jsmDeployment.jsmContainer.created ?: devDeployment.jsmDeployment.jsmContainer.enableJvmDebug(this.jsmJvmDebugPort)
169+
devDeployment.jsmDeployment.setJiraLicense(this.jsmLicense)
170+
devDeployment.jsmDeployment.jsmContainer.enableAppUpload()
171+
if (enableJsmDooD) {
172+
devDeployment.jsmDeployment.jsmContainer.prepareBindMount("/var/run/docker.sock", "/var/run/docker.sock", false)
173+
}
174+
devDeployment.jsmDeployment.appsToInstall = this.appsToInstall
175+
176+
177+
return devDeployment
178+
179+
}
180+
181+
}
182+
183+
184+
}
185+
186+

0 commit comments

Comments
 (0)