Skip to content

Commit b4e437b

Browse files
committed
more tests + add support for missing location
undo accidental delete fix another fix formatting remove extra log
1 parent 2af8d35 commit b4e437b

File tree

3 files changed

+155
-26
lines changed

3 files changed

+155
-26
lines changed

supportedBackends/google/batch/src/main/scala/cromwell/backend/google/batch/actors/GcpBatchAsyncBackendJobExecutionActor.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,18 @@ class GcpBatchAsyncBackendJobExecutionActor(override val standardParams: Standar
10131013
} yield status
10141014
}
10151015

1016+
override val pollingResultMonitorActor: Option[ActorRef] = Option(
1017+
context.actorOf(
1018+
BatchPollResultMonitorActor.props(serviceRegistryActor,
1019+
workflowDescriptor,
1020+
jobDescriptor,
1021+
validatedRuntimeAttributes,
1022+
platform,
1023+
jobLogger
1024+
)
1025+
)
1026+
)
1027+
10161028
override def isTerminal(runStatus: RunStatus): Boolean =
10171029
runStatus match {
10181030
case _: RunStatus.TerminalRunStatus => true

supportedBackends/google/batch/src/main/scala/cromwell/backend/google/batch/api/request/BatchRequestExecutor.scala

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import cromwell.backend.google.batch.api.{BatchApiRequestManager, BatchApiRespon
1313
import cromwell.backend.google.batch.models.{GcpBatchExitCode, RunStatus}
1414
import cromwell.core.ExecutionEvent
1515
import cromwell.services.cost.InstantiatedVmInfo
16+
import cromwell.services.metadata.CallMetadataKeys
1617

1718
import scala.annotation.unused
1819
import scala.concurrent.{ExecutionContext, Future, Promise}
@@ -146,9 +147,14 @@ object BatchRequestExecutor {
146147
val machineType = instancePolicy.getMachineType
147148
val preemtible = instancePolicy.getProvisioningModelValue == ProvisioningModel.PREEMPTIBLE.getNumber
148149

149-
// Each location can be a region or a zone. Only one region is supported, ex: "regions/us-central1"
150-
val location = allocationPolicy.getLocation.getAllowedLocations(0)
151-
val region = location.split("/").last
150+
// location list = [regions/us-central1, zones/us-central1-b], region is the first element
151+
val location = allocationPolicy.getLocation.getAllowedLocationsList.get(0)
152+
val region =
153+
if (location.isEmpty)
154+
"us-central1"
155+
else
156+
location.split("/").last
157+
152158
val instantiatedVmInfo = Some(InstantiatedVmInfo(region, machineType, preemtible))
153159

154160
if (job.getStatus.getState == JobStatus.State.SUCCEEDED) {
@@ -167,12 +173,20 @@ object BatchRequestExecutor {
167173
GcpBatchExitCode.fromEventMessage(e.name.toLowerCase)
168174
}.headOption
169175

170-
private def getEventList(events: List[StatusEvent]): List[ExecutionEvent] =
176+
private def getEventList(events: List[StatusEvent]): List[ExecutionEvent] = {
177+
val startedRegex = ".*SCHEDULED to RUNNING.*".r
178+
val endedRegex = ".*RUNNING to.*".r // can be SUCCEEDED or FAILED
171179
events.map { e =>
172180
val time = java.time.Instant
173181
.ofEpochSecond(e.getEventTime.getSeconds, e.getEventTime.getNanos.toLong)
174182
.atOffset(java.time.ZoneOffset.UTC)
175-
ExecutionEvent(name = e.getDescription, offsetDateTime = time)
183+
val eventType = e.getDescription match {
184+
case startedRegex() => CallMetadataKeys.VmStartTime
185+
case endedRegex() => CallMetadataKeys.VmEndTime
186+
case _ => e.getType
187+
}
188+
ExecutionEvent(name = eventType, offsetDateTime = time)
176189
}
190+
}
177191
}
178192
}

supportedBackends/google/batch/src/test/scala/cromwell/backend/google/batch/api/BatchRequestExecutorSpec.scala

Lines changed: 124 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,10 @@ package cromwell.backend.google.batch.api.request
22

33
import akka.actor.ActorSystem
44
import akka.testkit.TestKit
5-
import com.google.cloud.batch.v1.{
6-
AllocationPolicy,
7-
BatchServiceClient,
8-
BatchServiceSettings,
9-
GetJobRequest,
10-
Job,
11-
JobStatus
12-
}
13-
import com.google.cloud.batch.v1.AllocationPolicy.{
14-
InstancePolicy,
15-
InstancePolicyOrTemplate,
16-
LocationPolicy,
17-
ProvisioningModel
18-
}
5+
import com.google.cloud.batch.v1.{AllocationPolicy, BatchServiceClient, BatchServiceSettings, GetJobRequest, Job, JobStatus, StatusEvent}
6+
import com.google.cloud.batch.v1.AllocationPolicy.{InstancePolicy, InstancePolicyOrTemplate, LocationPolicy, ProvisioningModel}
7+
import com.google.cloud.batch.v1.JobStatus.State
8+
import com.google.protobuf.Timestamp
199
import common.mock.MockSugar
2010
import cromwell.backend.google.batch.api.BatchApiResponse
2111
import cromwell.backend.google.batch.models.RunStatus
@@ -32,30 +22,57 @@ class BatchRequestExecutorSpec
3222
with MockSugar
3323
with PrivateMethodTester {
3424

35-
behavior of "BatchRequestExecutor"
36-
37-
it should "create instantiatedVmInfo correctly" in {
38-
25+
def setupBatchClient(machineType: String = "n1-standard-1",
26+
location: String = "regions/us-central1",
27+
jobState: State = JobStatus.State.SUCCEEDED
28+
): BatchServiceClient = {
3929
val instancePolicy = InstancePolicy
4030
.newBuilder()
41-
.setMachineType("n1-standard-1")
31+
.setMachineType(machineType)
4232
.setProvisioningModel(ProvisioningModel.PREEMPTIBLE)
4333
.build()
4434

4535
val allocationPolicy = AllocationPolicy
4636
.newBuilder()
47-
.setLocation(LocationPolicy.newBuilder().addAllowedLocations("regions/us-central1"))
37+
.setLocation(LocationPolicy.newBuilder().addAllowedLocations(location))
4838
.addInstances(InstancePolicyOrTemplate.newBuilder().setPolicy(instancePolicy))
4939
.build()
5040

51-
val jobStatus = JobStatus.newBuilder().setState(JobStatus.State.RUNNING).build()
41+
val startStatusEvent = StatusEvent
42+
.newBuilder()
43+
.setType("STATUS_CHANGED")
44+
.setEventTime(Timestamp.newBuilder().setSeconds(1).build())
45+
.setDescription("Job state is set from SCHEDULED to RUNNING for job...")
46+
.build()
47+
48+
val endStatusEvent = StatusEvent
49+
.newBuilder()
50+
.setType("STATUS_CHANGED")
51+
.setEventTime(Timestamp.newBuilder().setSeconds(2).build())
52+
.setDescription("Job state is set from RUNNING to SOME_OTHER_STATUS for job...")
53+
.build()
54+
55+
val jobStatus = JobStatus
56+
.newBuilder()
57+
.setState(jobState)
58+
.addStatusEvents(startStatusEvent)
59+
.addStatusEvents(endStatusEvent)
60+
.build()
5261

5362
val job = Job.newBuilder().setAllocationPolicy(allocationPolicy).setStatus(jobStatus).build()
5463

5564
val mockClient = mock[BatchServiceClient]
5665
doReturn(job).when(mockClient).getJob(any[GetJobRequest])
5766
doReturn(job).when(mockClient).getJob(any[String])
5867

68+
mockClient
69+
}
70+
71+
behavior of "BatchRequestExecutor"
72+
73+
it should "create instantiatedVmInfo correctly" in {
74+
75+
val mockClient = setupBatchClient(jobState = JobStatus.State.RUNNING)
5976
// Create the BatchRequestExecutor
6077
val batchRequestExecutor = new BatchRequestExecutor.CloudImpl(BatchServiceSettings.newBuilder().build())
6178

@@ -72,4 +89,90 @@ class BatchRequestExecutorSpec
7289
case _ => fail("Expected RunStatus.Running with instantiatedVmInfo")
7390
}
7491
}
92+
93+
it should "create instantiatedVmInfo correctly with different location info" in {
94+
95+
val mockClient = setupBatchClient(location = "zones/us-central1-a", jobState = JobStatus.State.RUNNING)
96+
97+
// Create the BatchRequestExecutor
98+
val batchRequestExecutor = new BatchRequestExecutor.CloudImpl(BatchServiceSettings.newBuilder().build())
99+
100+
// testing a private method see https://www.scalatest.org/user_guide/using_PrivateMethodTester
101+
val internalGetHandler = PrivateMethod[BatchApiResponse.StatusQueried](Symbol("internalGetHandler"))
102+
val result = batchRequestExecutor invokePrivate internalGetHandler(mockClient, GetJobRequest.newBuilder().build())
103+
104+
// Verify the instantiatedVmInfo
105+
result.status match {
106+
case RunStatus.Running(_, Some(instantiatedVmInfo)) =>
107+
instantiatedVmInfo.region shouldBe "us-central1-a"
108+
instantiatedVmInfo.machineType shouldBe "n1-standard-1"
109+
instantiatedVmInfo.preemptible shouldBe true
110+
case _ => fail("Expected RunStatus.Running with instantiatedVmInfo")
111+
}
112+
}
113+
114+
it should "create instantiatedVmInfo correctly with missing location info" in {
115+
116+
val mockClient = setupBatchClient(jobState = JobStatus.State.RUNNING)
117+
118+
// Create the BatchRequestExecutor
119+
val batchRequestExecutor = new BatchRequestExecutor.CloudImpl(BatchServiceSettings.newBuilder().build())
120+
121+
// testing a private method see https://www.scalatest.org/user_guide/using_PrivateMethodTester
122+
val internalGetHandler = PrivateMethod[BatchApiResponse.StatusQueried](Symbol("internalGetHandler"))
123+
val result = batchRequestExecutor invokePrivate internalGetHandler(mockClient, GetJobRequest.newBuilder().build())
124+
125+
// Verify the instantiatedVmInfo
126+
result.status match {
127+
case RunStatus.Running(_, Some(instantiatedVmInfo)) =>
128+
instantiatedVmInfo.region shouldBe "us-central1"
129+
instantiatedVmInfo.machineType shouldBe "n1-standard-1"
130+
instantiatedVmInfo.preemptible shouldBe true
131+
case _ => fail("Expected RunStatus.Running with instantiatedVmInfo")
132+
}
133+
}
134+
135+
it should "send vmStartTime and vmEndTime metadata info when a workflow succeeds" in {
136+
137+
val mockClient = setupBatchClient()
138+
139+
// Create the BatchRequestExecutor
140+
val batchRequestExecutor = new BatchRequestExecutor.CloudImpl(BatchServiceSettings.newBuilder().build())
141+
142+
// testing a private method see https://www.scalatest.org/user_guide/using_PrivateMethodTester
143+
val internalGetHandler = PrivateMethod[BatchApiResponse.StatusQueried](Symbol("internalGetHandler"))
144+
val result = batchRequestExecutor invokePrivate internalGetHandler(mockClient, GetJobRequest.newBuilder().build())
145+
146+
// Verify the events
147+
result.status match {
148+
case RunStatus.Success(events, _) =>
149+
val eventNames = events.map(_.name)
150+
val eventTimes = events.map(_.offsetDateTime.toString)
151+
eventNames should contain theSameElementsAs List("vmStartTime", "vmEndTime")
152+
eventTimes should contain theSameElementsAs List("1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z")
153+
case _ => fail("Expected RunStatus.Success with events")
154+
}
155+
}
156+
157+
it should "send vmStartTime and vmEndTime metadata info when a workflow fails" in {
158+
val mockClient = setupBatchClient(jobState = JobStatus.State.FAILED)
159+
160+
// Create the BatchRequestExecutor
161+
val batchRequestExecutor = new BatchRequestExecutor.CloudImpl(BatchServiceSettings.newBuilder().build())
162+
163+
// testing a private method see https://www.scalatest.org/user_guide/using_PrivateMethodTester
164+
val internalGetHandler = PrivateMethod[BatchApiResponse.StatusQueried](Symbol("internalGetHandler"))
165+
val result = batchRequestExecutor invokePrivate internalGetHandler(mockClient, GetJobRequest.newBuilder().build())
166+
167+
// Verify the events
168+
result.status match {
169+
case RunStatus.Failed(_, events, _) =>
170+
val eventNames = events.map(_.name)
171+
val eventTimes = events.map(_.offsetDateTime.toString)
172+
eventNames should contain theSameElementsAs List("vmStartTime", "vmEndTime")
173+
eventTimes should contain theSameElementsAs List("1970-01-01T00:00:01Z", "1970-01-01T00:00:02Z")
174+
case _ => fail("Expected RunStatus.Success with events")
175+
}
176+
}
177+
75178
}

0 commit comments

Comments
 (0)