@@ -35,6 +35,7 @@ import org.slf4j.LoggerFactory
3535import java.nio.file.Files
3636import java.nio.file.Path
3737import java.time.Duration
38+ import java.util.concurrent.TimeoutException
3839import java.util.regex.Matcher
3940import java.util.regex.Pattern
4041
@@ -91,8 +92,17 @@ trait Container {
9192
9293 }
9394
94- return containerCreateRequest
95+ return customizeContainerCreateRequest(containerCreateRequest)
96+
97+ }
9598
99+ /**
100+ * Helper method that allows you to easily customize the ContainerCreateRequest by overriding just this method
101+ * @param containerCreateRequest
102+ * @return
103+ */
104+ ContainerCreateRequest customizeContainerCreateRequest(ContainerCreateRequest containerCreateRequest) {
105+ return containerCreateRequest
96106 }
97107
98108 /**
@@ -108,7 +118,7 @@ trait Container {
108118 ContainerCreateRequest containerCreateRequest = setupContainerCreateRequest()
109119
110120 if (cmd. size()) {
111- containerCreateRequest. cmd = cmd
121+ containerCreateRequest. cmd = cmd. collect {it . toString()}
112122 }
113123
114124 if (entrypoint. size()) {
@@ -180,7 +190,7 @@ trait Container {
180190 return containerId
181191 }
182192
183- def getSelf() {
193+ Container getSelf() {
184194 return this
185195 }
186196
@@ -625,7 +635,7 @@ trait Container {
625635 }
626636
627637 /**
628- * Copy files from a container
638+ * Copy files from a container to local machine
629639 * @param containerPath can be a file or a path (ending in /)
630640 * @param destinationPath
631641 * @return
@@ -712,6 +722,121 @@ trait Container {
712722 return runCommandInContainer(self. containerId, [self. defaultShell, " -c" , command], timeoutS, user)
713723
714724
725+ }
726+
727+ /**
728+ * Creates an temporary container, runs a command, exits and removes container
729+ * @param cmd A string that will be passed as a command to /bin/sh -c, ex: echo start;sleep 5
730+ * @param timeoutMs
731+ * 0 don't wait, return an array with the container ID immediately,
732+ * timeoutMs > 0 Wait for container to stop, if it takes longer than timeoutMs an exception will be thrown
733+ * @param mounts bind mounts that the container should have:
734+ * readOnly is optional and defaults to true
735+ * ex:[[src: "/tmp/engine/test", target: "/tmp/container/test", readOnly :true]
736+ * @param dockerHost
737+ * @param dockerCertPath
738+ * @return An array of the container logs, or just an array containing container id if timeoutMs == 0
739+ */
740+ static ArrayList<String > runCmdAndRm(String cmd, long timeoutMs, ArrayList<Map > mounts = [], String dockerHost = " " , String dockerCertPath = " " ) {
741+
742+
743+ return runCmdAndRm([" /bin/sh" , " -c" , cmd], timeoutMs, mounts, dockerHost, dockerCertPath)
744+ }
745+
746+
747+
748+ /**
749+ * Creates a temporary container, runs a command, exits and removes container
750+ * @param container a container object that hasnt yet been created
751+ * @param cmd An array of commands to run, ex: [ "/bin/sh", "-c", "echo start;sleep 5"]
752+ * @param timeoutMs
753+ * 0 don't wait, return an array with the container ID immediately,
754+ * timeoutMs > 0 Wait for container to stop, if it takes longer than timeoutMs an exception will be thrown
755+ * @param mounts bind mounts that the container should have:
756+ * readOnly is optional and defaults to true
757+ * ex:[[src: "/tmp/engine/test", target: "/tmp/container/test", readOnly :true]
758+ * @param dockerHost
759+ * @param dockerCertPath
760+ * @return An array of the container logs, or just an array containing container id if timeoutMs == 0
761+ */
762+ static ArrayList<String > runCmdAndRm( ArrayList<String > cmd, long timeoutMs, ArrayList<Map > mounts = [], String dockerHost = " " , String dockerCertPath = " " ) {
763+
764+
765+ Container container = this . getConstructor(String , String ). newInstance(dockerHost, dockerCertPath)
766+
767+ Logger log = LoggerFactory . getLogger(this . class)
768+
769+
770+
771+ log. info(" Creating a $container . class . simpleName and running:" )
772+ log. info(" \t Cmd:" + cmd)
773+
774+
775+
776+ try {
777+
778+ container. containerName = container. containerName + " -cmd-" + System . currentTimeMillis(). toString()[-5 .. -1 ]
779+
780+ mounts. each {
781+ log. info(" \t Preparing Bind mount:" )
782+ container. prepareBindMount(it. src as String , it. target as String , it. containsKey(" readOnly" ) ? it. readOnly as Boolean : true )
783+ }
784+
785+
786+ container. createContainer(cmd)
787+ log. info(" \t Created container: " + container. id)
788+
789+
790+ log. info(" \t Started container: " + container. startContainer())
791+ assert ! container. hasNeverBeenStarted(): " Error starting CMD container"
792+
793+ if (timeoutMs == 0 ) {
794+ log. info(" \t No Timeout set, returning container id" )
795+ return [container. id]
796+ }
797+
798+ long start = System . currentTimeMillis()
799+
800+ while (start + timeoutMs > System . currentTimeMillis() && container. running) {
801+
802+ log. info(" \t Waited ${ System.currentTimeMillis() - start} ms for container to stop" )
803+ sleep(1000 )
804+
805+ }
806+ log. info(" \t Container finisehd or timed out after ${ System.currentTimeMillis() - start} ms" )
807+
808+ if (container. running) {
809+ log. info(" \t " * 2 + " Stopping container forcefully." )
810+ ArrayList<String > containerOut = container. containerLogs
811+ assert container. stopAndRemoveContainer(1 ): " Error stopping and removing CMD container after it timed out"
812+
813+ throw new TimeoutException (" CMD container timed out, was forcefully stopped and removed. Container logs:" + containerOut?. join(" \n " ))
814+ }
815+
816+
817+
818+ ArrayList<String > containerOut = container. containerLogs
819+
820+ log. info(" \t Returning ${ containerOut.size()} log lines" )
821+
822+ assert container. stopAndRemoveContainer(): " Error removing Container:" + container. id
823+ log. info(" \t Removed container:" + container. id)
824+
825+ return containerOut
826+ } catch (ex) {
827+
828+
829+ try {
830+ container. stopAndRemoveContainer(1 )
831+ } catch (ignored){}
832+
833+
834+
835+ throw ex
836+
837+ }
838+
839+
715840 }
716841
717842
@@ -747,7 +872,7 @@ trait Container {
747872 */
748873 void prepareCustomEnvVar(ArrayList<String > keyVar) {
749874
750- assert hasNeverBeenStarted(): " Error, cant set custom enviromental variables after creating container"
875+ assert hasNeverBeenStarted(): " Error, cant set custom environment variables after creating container"
751876
752877 self. customEnvVar = keyVar
753878 }
0 commit comments