Skip to content

Commit 4182c39

Browse files
authored
2.3.5 Adding Time Machine helpers (#25)
* 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
1 parent 3bb4d39 commit 4182c39

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
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.4-SNAPSHOT</version>
9+
<version>2.3.5-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<name>DevStack</name>

src/main/groovy/com/eficode/devstack/util/TimeMachine.groovy

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import org.slf4j.LoggerFactory
77

88
import java.time.Duration
99
import java.time.Instant
10+
import java.time.LocalDate
11+
import java.time.LocalDateTime
12+
import java.time.ZoneId
1013
import java.time.temporal.TemporalAdjuster
1114

1215
/**
@@ -23,7 +26,7 @@ import java.time.temporal.TemporalAdjuster
2326
* you change it for all running containers
2427
*
2528
*/
26-
class TimeMachine implements Container{
29+
class TimeMachine implements Container {
2730

2831
String containerName = "TimeMachine"
2932
String containerMainPort = null
@@ -32,7 +35,6 @@ class TimeMachine implements Container{
3235
String defaultShell = "/bin/sh"
3336

3437

35-
3638
/**
3739
* Travel back to the present
3840
* <b>NEVER EVER</b> use this class on a production docker engine <p>
@@ -42,11 +44,12 @@ class TimeMachine implements Container{
4244
* @return true after verifying success
4345
*/
4446
static boolean travelToNow(String dockerHost = "", String dockerCertPath = "") {
47+
4548
return setTime(System.currentTimeSeconds(), dockerHost, dockerCertPath)
4649
}
4750

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

59-
long newEpochS = System.currentTimeSeconds() + Duration.ofDays(days).toSeconds()
62+
long newEpochS = System.currentTimeSeconds() + Duration.ofDays(days).toSeconds()
6063

6164
return setTime(newEpochS, dockerHost, dockerCertPath)
6265

6366
}
6467

68+
/**
69+
* Travel X days in time relative to
70+
* <b>NEVER EVER</b> use this class on a production docker engine <p>
71+
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
72+
* @param days Number of days to travel, can be negative (to the past) or positive (to the future)
73+
* @param dockerHost optional
74+
* @param dockerCertPath optional
75+
* @return true after verifying success
76+
*/
77+
static boolean travelRelativeDays(int days, String dockerHost = "", String dockerCertPath = "") {
78+
79+
long currentDockerTime = getDockerTime(dockerHost, dockerCertPath)
80+
81+
long newEpochS = currentDockerTime + Duration.ofDays(days).toSeconds()
82+
83+
return setTime(newEpochS, dockerHost, dockerCertPath)
84+
85+
}
86+
87+
/**
88+
* Set new time based on Date object
89+
* <b>NEVER EVER</b> use this class on a production docker engine <p>
90+
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
91+
* @param date A date object to use as the new "now"
92+
* @param dockerHost optional
93+
* @param dockerCertPath optional
94+
* @return true after verifying success
95+
*/
96+
static boolean setDate(Date date, String dockerHost = "", String dockerCertPath = "") {
97+
return setTime(((date.toInstant().toEpochMilli()) / 1000).toInteger(), dockerHost, dockerCertPath)
98+
}
99+
100+
/**
101+
* Set new time based on LocalDateTime object, uses the system default Time Zone
102+
* <b>NEVER EVER</b> use this class on a production docker engine <p>
103+
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
104+
* @param localDateTime A LocalDateTime object to use as the new "now"
105+
* @param dockerHost optional
106+
* @param dockerCertPath optional
107+
* @return true after verifying success
108+
*/
109+
static boolean setLocalDateTime(LocalDateTime localDateTime, String dockerHost = "", String dockerCertPath = "") {
110+
111+
return setTime(localDateTime.toEpochSecond(ZoneId.systemDefault().offset), dockerHost, dockerCertPath)
112+
}
113+
114+
/**
115+
* Set new time based on LocalDate object
116+
* <b>NEVER EVER</b> use this class on a production docker engine <p>
117+
* <b>WARNING THIS AFFECTS ALL CONTAINERS - READ CLASS DOCUMENTATION</b>
118+
* @param LocalDate A LocalDate object to use as the new "now"
119+
* @param dockerHost optional
120+
* @param dockerCertPath optional
121+
* @return true after verifying success
122+
*/
123+
static boolean setLocalDate(LocalDate localDate, String dockerHost = "", String dockerCertPath = "") {
124+
125+
return setTime(localDate.toEpochDay(), dockerHost, dockerCertPath)
126+
}
127+
65128

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

81144

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

149+
long newTime = getDockerTime(dockerHost, dockerCertPath)
88150

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

93153
return true
94154

95155
}
96156

157+
/**
158+
* Get current time as reported by a docker container
159+
* @param dockerHost
160+
* @param dockerCertPath
161+
* @return Epoch Seconds
162+
*/
163+
static long getDockerTime(String dockerHost = "", String dockerCertPath = "") {
164+
165+
ArrayList<String> cmdOut = runCmdAndRm('date +"%s"', 5000, [], dockerHost, dockerCertPath)
166+
long timeStamp = cmdOut.find { it.isNumber() }?.toLong() ?: 0
167+
assert timeStamp: "Unexpected output when getting docker time"
168+
169+
return timeStamp
170+
171+
}
97172

98173

99174
@Override
100-
ContainerCreateRequest customizeContainerCreateRequest(ContainerCreateRequest containerCreateRequest){
175+
ContainerCreateRequest customizeContainerCreateRequest(ContainerCreateRequest containerCreateRequest) {
101176

102177

103178
containerCreateRequest.hostConfig.setPrivileged(true)

0 commit comments

Comments
 (0)