Skip to content

Commit

Permalink
2.3.5 Adding Time Machine helpers (#25)
Browse files Browse the repository at this point in the history
* pom.xml
 Bumped to 2.3.2
 Bumped DockerClient to 2023-05-07T23-22-00

* pom.xml
 * Bumped to 2.3.3
JsmContainer.groovy
 * Added enableJvmDebug()

* AlpineContainer.groovy
 * Moved the runCmdAndRm() and runCmdAndRm() to the interface class Container

Container.groovy
 * added customizeContainerCreateRequest() that allows implementing methods to easily override parts of the ContainerCreateRequest
 * added runCmdAndRm()

TimeMachine.groovy
 * A new helper method for traveling in time!
pom.xml
 * Bumped to 2.3.4

* TimeMachine.groovy
 * Added several helper set methods for different time/date classes
pom.xml
 * Bumped to 2.3.5
  • Loading branch information
farthinder authored Sep 13, 2023
1 parent 3bb4d39 commit 4182c39
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 14 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.eficode</groupId>
<artifactId>devstack</artifactId>
<version>2.3.4-SNAPSHOT</version>
<version>2.3.5-SNAPSHOT</version>
<packaging>jar</packaging>

<name>DevStack</name>
Expand Down
101 changes: 88 additions & 13 deletions src/main/groovy/com/eficode/devstack/util/TimeMachine.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import org.slf4j.LoggerFactory

import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.temporal.TemporalAdjuster

/**
Expand All @@ -23,7 +26,7 @@ import java.time.temporal.TemporalAdjuster
* you change it for all running containers
*
*/
class TimeMachine implements Container{
class TimeMachine implements Container {

String containerName = "TimeMachine"
String containerMainPort = null
Expand All @@ -32,7 +35,6 @@ class TimeMachine implements Container{
String defaultShell = "/bin/sh"



/**
* Travel back to the present
* <b>NEVER EVER</b> use this class on a production docker engine <p>
Expand All @@ -42,11 +44,12 @@ class TimeMachine implements Container{
* @return true after verifying success
*/
static boolean travelToNow(String dockerHost = "", String dockerCertPath = "") {

return setTime(System.currentTimeSeconds(), dockerHost, dockerCertPath)
}

/**
* Travel X days in time
* Travel X days in time from actual "Now"
* <b>NEVER EVER</b> use this class on a production docker engine <p>
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
* @param days Number of days to travel, can be negative (to the past) or positive (to the future)
Expand All @@ -56,12 +59,72 @@ class TimeMachine implements Container{
*/
static boolean travelDays(int days, String dockerHost = "", String dockerCertPath = "") {

long newEpochS = System.currentTimeSeconds() + Duration.ofDays(days).toSeconds()
long newEpochS = System.currentTimeSeconds() + Duration.ofDays(days).toSeconds()

return setTime(newEpochS, dockerHost, dockerCertPath)

}

/**
* Travel X days in time relative to
* <b>NEVER EVER</b> use this class on a production docker engine <p>
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
* @param days Number of days to travel, can be negative (to the past) or positive (to the future)
* @param dockerHost optional
* @param dockerCertPath optional
* @return true after verifying success
*/
static boolean travelRelativeDays(int days, String dockerHost = "", String dockerCertPath = "") {

long currentDockerTime = getDockerTime(dockerHost, dockerCertPath)

long newEpochS = currentDockerTime + Duration.ofDays(days).toSeconds()

return setTime(newEpochS, dockerHost, dockerCertPath)

}

/**
* Set new time based on Date object
* <b>NEVER EVER</b> use this class on a production docker engine <p>
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
* @param date A date object to use as the new "now"
* @param dockerHost optional
* @param dockerCertPath optional
* @return true after verifying success
*/
static boolean setDate(Date date, String dockerHost = "", String dockerCertPath = "") {
return setTime(((date.toInstant().toEpochMilli()) / 1000).toInteger(), dockerHost, dockerCertPath)
}

/**
* Set new time based on LocalDateTime object, uses the system default Time Zone
* <b>NEVER EVER</b> use this class on a production docker engine <p>
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
* @param localDateTime A LocalDateTime object to use as the new "now"
* @param dockerHost optional
* @param dockerCertPath optional
* @return true after verifying success
*/
static boolean setLocalDateTime(LocalDateTime localDateTime, String dockerHost = "", String dockerCertPath = "") {

return setTime(localDateTime.toEpochSecond(ZoneId.systemDefault().offset), dockerHost, dockerCertPath)
}

/**
* Set new time based on LocalDate object
* <b>NEVER EVER</b> use this class on a production docker engine <p>
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
* @param LocalDate A LocalDate object to use as the new "now"
* @param dockerHost optional
* @param dockerCertPath optional
* @return true after verifying success
*/
static boolean setLocalDate(LocalDate localDate, String dockerHost = "", String dockerCertPath = "") {

return setTime(localDate.toEpochDay(), dockerHost, dockerCertPath)
}


/**
* Change docker engine time <p>
Expand All @@ -79,25 +142,37 @@ class TimeMachine implements Container{
log.warn("THIS WILL AFFECT ALL CONTAINERS RUN BY THIS DOCKER ENGINE")


assert epochS <= 9999999999 && epochS > 1000000000 : "Provide timestamp in epoch seconds"
ArrayList<String> cmdOut = runCmdAndRm(["nsenter" ,"-t" ,"1" ,"-m" ,"-u" ,"-n", "-i", "sh", "-c", "pkill sntpc || date -s \"@${epochS}\" && echo Status \$?"], 5000, [] , dockerHost, dockerCertPath)
assert cmdOut.toString().contains("Status 0") : "Error setting time"

cmdOut = runCmdAndRm('date +"%s"', 5000, [], dockerHost, dockerCertPath )
assert epochS <= 9999999999 && epochS > 1000000000: "Provide timestamp in epoch seconds"
ArrayList<String> cmdOut = runCmdAndRm(["nsenter", "-t", "1", "-m", "-u", "-n", "-i", "sh", "-c", "pkill sntpc || date -s \"@${epochS}\" && echo Status \$?"], 5000, [], dockerHost, dockerCertPath)
assert cmdOut.toString().contains("Status 0"): "Error setting time"

long newTime = getDockerTime(dockerHost, dockerCertPath)

long newTime = cmdOut.find {it.isNumber()}?.toLong() ?: 0
assert newTime : "Unexpected output when verifying time was change"
assert newTime >= epochS : "The newly set time appears incorrect: " + newTime
assert newTime >= epochS: "The newly set time appears incorrect: " + newTime

return true

}

/**
* Get current time as reported by a docker container
* @param dockerHost
* @param dockerCertPath
* @return Epoch Seconds
*/
static long getDockerTime(String dockerHost = "", String dockerCertPath = "") {

ArrayList<String> cmdOut = runCmdAndRm('date +"%s"', 5000, [], dockerHost, dockerCertPath)
long timeStamp = cmdOut.find { it.isNumber() }?.toLong() ?: 0
assert timeStamp: "Unexpected output when getting docker time"

return timeStamp

}


@Override
ContainerCreateRequest customizeContainerCreateRequest(ContainerCreateRequest containerCreateRequest){
ContainerCreateRequest customizeContainerCreateRequest(ContainerCreateRequest containerCreateRequest) {


containerCreateRequest.hostConfig.setPrivileged(true)
Expand Down

0 comments on commit 4182c39

Please sign in to comment.