11package com.eficode.devstack.container
22
3- import de.gesellix.docker.client.DockerClientImpl
3+ import com.eficode.devstack.util.DockerClientDS
44import de.gesellix.docker.client.EngineResponseContent
55import de.gesellix.docker.client.network.ManageNetworkClient
66import de.gesellix.docker.engine.DockerClientConfig
@@ -11,6 +11,7 @@ import de.gesellix.docker.remote.api.ContainerInspectResponse
1111import de.gesellix.docker.remote.api.ContainerState
1212import de.gesellix.docker.remote.api.ContainerSummary
1313import de.gesellix.docker.remote.api.EndpointSettings
14+ import de.gesellix.docker.remote.api.ExecConfig
1415import de.gesellix.docker.remote.api.HostConfig
1516import de.gesellix.docker.remote.api.IdResponse
1617import de.gesellix.docker.remote.api.Mount
@@ -40,21 +41,20 @@ import java.util.regex.Pattern
4041trait Container {
4142
4243 Logger log = LoggerFactory . getLogger(self. class)
43- DockerClientImpl dockerClient = new DockerClientImpl ()
44+ DockerClientDS dockerClient = new DockerClientDS ()
4445 ManageNetworkClient networkClient = dockerClient. getManageNetwork() as ManageNetworkClient
4546 abstract String containerName
4647 abstract String containerMainPort
4748 abstract String containerImage
4849 abstract String containerImageTag
50+ ArrayList<String > containerDefaultNetworks = [" bridge" ]
4951 ArrayList<String > customEnvVar = []
50- // String containerNetworkName = "bridge"
5152 String defaultShell = " /bin/bash"
5253 String containerId
5354 ArrayList<Mount > mounts = []
5455
5556
5657 void prepareBindMount(String sourceAbs, String target, boolean readOnly = true ) {
57- assert ! isCreated(): " Bind mounts cant be prepared for already created container"
5858
5959 Mount newMount = new Mount (). tap { m ->
6060 m. source = sourceAbs
@@ -89,7 +89,6 @@ trait Container {
8989 c. hostname = self. containerName
9090 c. env = self. customEnvVar
9191
92-
9392 }
9493
9594 return containerCreateRequest
@@ -98,11 +97,11 @@ trait Container {
9897
9998 /**
10099 * Create container and override default docker cmd and entrypoint
101- * @param cmd:
100+ * @param cmd :
102101 * @param entrypoint ex: ["tail", "-f", "/dev/null"]
103102 * @return container id
104103 */
105- String createContainer(ArrayList<String > cmd, ArrayList<String > entrypoint) {
104+ String createContainer(ArrayList<String > cmd = [] , ArrayList<String > entrypoint = [] ) {
106105
107106 assert ping(): " Error connecting to docker engine"
108107
@@ -119,14 +118,14 @@ trait Container {
119118 EngineResponseContent response = dockerClient. createContainer(containerCreateRequest, self. containerName)
120119 assert response. content. warnings. isEmpty(): " Error when creating ${ self.containerName} container:" + response. content. warnings. join(" ," )
121120
121+ ArrayList<Network > networks = containerDefaultNetworks. collect { createBridgeNetwork(it) }
122+ assert setContainerNetworks(networks): " Error setting container networks to:" + containerDefaultNetworks
123+
122124 containerId = response. content. id
123125 return containerId
124126
125127 }
126128
127- String createContainer() {
128- return createContainer([], [])
129- }
130129
131130 boolean runOnFirstStartup() {
132131 return true
@@ -145,7 +144,7 @@ trait Container {
145144 dockerEnv. setCertPath(certPath)
146145 dockerEnv. setTlsVerify(" 1" )
147146 dockerConfig. apply(dockerEnv)
148- dockerClient = new DockerClientImpl (dockerConfig)
147+ dockerClient = new DockerClientDS (dockerConfig)
149148 networkClient = dockerClient. getManageNetwork() as ManageNetworkClient
150149
151150
@@ -248,10 +247,8 @@ trait Container {
248247
249248 if (status == ContainerState.Status.Created ) {
250249 return true // Created but not started
251- } else if (status == null ) {
252- return true // Not even created
253250 } else {
254- return false
251+ return status == null
255252 }
256253
257254 }
@@ -270,7 +267,7 @@ trait Container {
270267 }
271268
272269 ContainerState.Status status() {
273- return inspectContainer(). state. status
270+ return inspectContainer()? . state? . status
274271 }
275272
276273 boolean stopAndRemoveContainer(Integer timeoutS = 5 ) {
@@ -469,28 +466,39 @@ trait Container {
469466 * @param networkNameOrId
470467 * @return Network if found, null if not
471468 */
472- Network getNetwork (String networkNameOrId) {
469+ Network getDockerNetwork (String networkNameOrId) {
473470
474471
475472 Network network = networkClient. networks(). content. find { it. name == networkNameOrId || it. id == networkNameOrId }
476473
477474 return network
478475 }
476+ /**
477+ * Gets networks based on name or id, note there might be multiple networks with the same name
478+ * @param networkNameOrIds
479+ * @return Networks if found, null if not
480+ */
481+ ArrayList<Network > getDockerNetworks(ArrayList<String > networkNameOrIds) {
482+
483+ ArrayList<Network > networks = networkClient. networks(). content. findAll { it. name in networkNameOrIds || it. id in networkNameOrIds }
484+
485+ return networks
486+ }
479487
480488 boolean networkIsValid(Network network) {
481- return getNetwork (network. id) != null
489+ return getDockerNetwork (network. id) != null
482490 }
483491
484492 /**
485493 * Get the networks that this container is connected too
486494 * @return
487495 */
488- ArrayList<Network > getContainerNetworks () {
496+ ArrayList<Network > getConnectedContainerNetworks () {
489497 Map<String , EndpointSettings > rawResponse = inspectContainer(). networkSettings. networks
490498
491499 ArrayList<Network > networks = []
492500 rawResponse. keySet(). each { networkId ->
493- Network network = getNetwork (networkId)
501+ Network network = getDockerNetwork (networkId)
494502
495503 if (network != null ) {
496504 networks. add(network)
@@ -509,7 +517,7 @@ trait Container {
509517 ArrayList<Network > getContainerBridgeNetworks() {
510518
511519
512- return getContainerNetworks (). findAll { it. driver == " bridge" }
520+ return getConnectedContainerNetworks (). findAll { it. driver == " bridge" }
513521
514522 }
515523
@@ -533,7 +541,7 @@ trait Container {
533541 log. trace(" \t Verifying container was added to network" )
534542
535543
536- if (containerNetworks . find { it. id == network. id } != null ) {
544+ if (connectedContainerNetworks . find { it. id == network. id } != null ) {
537545 log. info(" \t Container was successfully added to network" )
538546 return true
539547 }
@@ -550,7 +558,7 @@ trait Container {
550558 networkClient. disconnectNetwork(network. id, containerId)
551559 log. trace(" \t Verifying container was disconnected from network" )
552560
553- if (! containerNetworks . find { it. id == network. id }) {
561+ if (! connectedContainerNetworks . find { it. id == network. id }) {
554562 log. info(" \t Container was successfully disconnected from network" )
555563 return true
556564 }
@@ -569,8 +577,7 @@ trait Container {
569577
570578 log. info(" Setting container networks" )
571579 log. info(" \t Beginning by disconnecting any networks it should no longer be connected to" )
572- ArrayList networks = containerNetworks
573- containerNetworks. each { connectedNetwork ->
580+ connectedContainerNetworks. each { connectedNetwork ->
574581
575582 if (newNetworks. id. find { newNetworkId -> newNetworkId != connectedNetwork. id }) {
576583 assert disconnectContainerFromNetwork(connectedNetwork): " Error disconnecting container (${ containerName} ) from network: ${ connectedNetwork.name} (${ connectedNetwork.id} )"
@@ -580,7 +587,7 @@ trait Container {
580587 }
581588 log. info(" \t Finished disconnecting container from unwanted networks, now connecting to new networks" )
582589
583- ArrayList<Network > connectedNetworks = containerNetworks
590+ ArrayList<Network > connectedNetworks = connectedContainerNetworks
584591 newNetworks. each { wantedNetwork ->
585592
586593 if (connectedNetworks. id. find { wantedNetwork. id }) {
@@ -644,23 +651,45 @@ trait Container {
644651 }
645652
646653
647- ArrayList<String > runBashCommandInContainer(String command, long timeoutS = 10 ) {
654+ // Format is one of: `user`, `user:group`, `uid`, or `uid:gid`
655+ ArrayList<String > runCommandInContainer(String containerId, ArrayList<String > commands, long timeoutS = 10 , String userGroup = null , String workingDir = null ) {
648656
649657 log. info(" Executing bash command in container:" )
650658 log. info(" \t Container:" + self. containerName + " (${ self.containerId} )" )
651- log. info(" \t Command:" + command )
659+ log. info(" \t Command:" + commands )
652660 log. info(" \t Timeout:" + timeoutS)
653- if (log. isTraceEnabled()) {
654- log. trace(" \t Docker ping:" + dockerClient. ping(). content as String )
655- }
656-
657661
658662 long cmdStart = System . currentTimeMillis()
663+
664+ ExecConfig execConfig = new ExecConfig ()
665+ execConfig. with { ex ->
666+ ex. attachStdin = false
667+ ex. attachStdout = true
668+ ex. attachStderr = true
669+ ex. detachKeys = null
670+ ex. tty = false
671+ ex. env = null
672+ ex. cmd = commands
673+ ex. privileged = null
674+ ex. user = userGroup ?: null
675+ ex. workingDir = workingDir ?: null
676+ }
677+
659678 ContainerCallback callBack = new ContainerCallback ()
660- EngineResponse<IdResponse > response = dockerClient. exec(self. containerId, [self. defaultShell, " -c" , command], callBack, Duration . ofSeconds(timeoutS))
679+ dockerClient. exec(containerId, commands, callBack, Duration . ofSeconds(timeoutS), execConfig)
680+
681+ log. trace(" \t Command finished after:" + ((System . currentTimeMillis() - cmdStart) / 1000 ). round() + " s" )
661682
662- log. trace(" \t Command finished after:" + ((System . currentTimeMillis()- cmdStart)/ 1000 ). round() + " s" )
663683 return callBack. output
684+
685+ }
686+
687+
688+ ArrayList<String > runBashCommandInContainer(String command, long timeoutS = 10 , String user = null ) {
689+
690+ return runCommandInContainer(self. containerId, [self. defaultShell, " -c" , command], timeoutS, user)
691+
692+
664693 }
665694
666695
0 commit comments