Skip to content

Commit e4ee467

Browse files
feat: Batch create job with custom status events sample (GoogleCloudPlatform#12060)
* Add create_with_custom_status_events.py and update test_basics.py - Added new script to create jobs with custom events to describe job's runnables. - Modified test_basics.py to include tests for creating job with custom status events * Minor fixes * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Updated requirements.txt for the new version of cloud-batch. --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent fbf5017 commit e4ee467

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Copyright 2022 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
import google.auth
17+
18+
# [START batch_custom_events]
19+
from google.cloud import batch_v1
20+
21+
22+
def create_job_with_status_events(
23+
project_id: str, region: str, job_name: str
24+
) -> batch_v1.Job:
25+
"""
26+
This method shows the creation of a Batch job with custom status events which describe runnables
27+
Within the method, the state of a runnable is described by defining its display name.
28+
The script text is modified to change the commands that are executed, and barriers are adjusted
29+
to synchronize tasks at specific points.
30+
31+
Args:
32+
project_id (str): project ID or project number of the Cloud project you want to use.
33+
region (str): name of the region you want to use to run the job. Regions that are
34+
available for Batch are listed on: https://cloud.google.com/batch/docs/locations
35+
job_name (str): the name of the job that will be created.
36+
It needs to be unique for each project and region pair.
37+
38+
Returns:
39+
A job object representing the job created with additional runnables and custom events.
40+
"""
41+
client = batch_v1.BatchServiceClient()
42+
43+
# Executes a simple script that prints a message.
44+
runn1 = batch_v1.Runnable()
45+
runn1.display_name = "Script 1"
46+
runn1.script.text = "echo Hello world from Script 1 for task ${BATCH_TASK_INDEX}"
47+
48+
# Acts as a barrier to synchronize the execution of subsequent runnables.
49+
runn2 = batch_v1.Runnable()
50+
runn2.display_name = "Barrier 1"
51+
runn2.barrier = batch_v1.Runnable.Barrier({"name": "hello-barrier"})
52+
53+
# Executes another script that prints a message, intended to run after the barrier.
54+
runn3 = batch_v1.Runnable()
55+
runn3.display_name = "Script 2"
56+
runn3.script.text = "echo Hello world from Script 2 for task ${BATCH_TASK_INDEX}"
57+
58+
# Executes a script that imitates a delay and creates a custom event for monitoring purposes.
59+
runn4 = batch_v1.Runnable()
60+
runn4.script.text = (
61+
'sleep 30; echo \'{"batch/custom/event": "EVENT_DESCRIPTION"}\'; sleep 30'
62+
)
63+
64+
# Jobs can be divided into tasks. In this case, we have only one task.
65+
task = batch_v1.TaskSpec()
66+
# Assigning a list of runnables to the task.
67+
task.runnables = [runn1, runn2, runn3, runn4]
68+
69+
# We can specify what resources are requested by each task.
70+
resources = batch_v1.ComputeResource()
71+
resources.cpu_milli = 2000 # in milliseconds per cpu-second. This means the task requires 2 whole CPUs.
72+
resources.memory_mib = 16 # in MiB
73+
task.compute_resource = resources
74+
75+
task.max_retry_count = 2
76+
task.max_run_duration = "3600s"
77+
78+
# Tasks are grouped inside a job using TaskGroups.
79+
# Currently, it's possible to have only one task group.
80+
group = batch_v1.TaskGroup()
81+
82+
group.task_count = 4
83+
group.task_spec = task
84+
85+
# Policies are used to define on what kind of virtual machines the tasks will run on.
86+
# In this case, we tell the system to use "e2-standard-4" machine type.
87+
# Read more about machine types here: https://cloud.google.com/compute/docs/machine-types
88+
policy = batch_v1.AllocationPolicy.InstancePolicy()
89+
policy.machine_type = "e2-standard-4"
90+
instances = batch_v1.AllocationPolicy.InstancePolicyOrTemplate()
91+
instances.policy = policy
92+
allocation_policy = batch_v1.AllocationPolicy()
93+
allocation_policy.instances = [instances]
94+
95+
job = batch_v1.Job()
96+
job.task_groups = [group]
97+
job.allocation_policy = allocation_policy
98+
job.labels = {"env": "testing", "type": "container"}
99+
# We use Cloud Logging as it's an out of the box available option
100+
job.logs_policy = batch_v1.LogsPolicy()
101+
job.logs_policy.destination = batch_v1.LogsPolicy.Destination.CLOUD_LOGGING
102+
103+
create_request = batch_v1.CreateJobRequest()
104+
create_request.job = job
105+
create_request.job_id = job_name
106+
# The job's parent is the region in which the job will run
107+
create_request.parent = f"projects/{project_id}/locations/{region}"
108+
109+
return client.create_job(create_request)
110+
111+
112+
# [END batch_custom_events]
113+
114+
115+
if __name__ == "__main__":
116+
PROJECT_ID = google.auth.default()[1]
117+
REGION = "europe-west4"
118+
job_name = "test-job-name"
119+
job = create_job_with_status_events(PROJECT_ID, REGION, job_name)
120+
print(job)

batch/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
google-cloud-batch==0.11.0
1+
google-cloud-batch==0.17.22
22
google-cloud-logging==3.5.0

batch/tests/test_basics.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import pytest
2626

2727
from ..create.create_with_container_no_mounting import create_container_job
28+
from ..create.create_with_custom_status_events import create_job_with_status_events
2829
from ..create.create_with_gpu_no_mounting import create_gpu_job
2930
from ..create.create_with_persistent_disk import create_with_pd_job
3031
from ..create.create_with_script_no_mounting import create_script_job
@@ -137,6 +138,24 @@ def _check_secret_set(job: batch_v1.Job, secret_name: str):
137138
assert secret_name in job.task_groups[0].task_spec.environment.secret_variables
138139

139140

141+
def _check_custom_events(job: batch_v1.Job):
142+
display_names = ["Script 1", "Barrier 1", "Script 2"]
143+
custom_event_found = False
144+
barrier_name_found = False
145+
146+
for runnable in job.task_groups[0].task_spec.runnables:
147+
if runnable.display_name in display_names:
148+
display_names.remove(runnable.display_name)
149+
if runnable.barrier.name == "hello-barrier":
150+
barrier_name_found = True
151+
if '{"batch/custom/event": "EVENT_DESCRIPTION"}' in runnable.script.text:
152+
custom_event_found = True
153+
154+
assert not display_names
155+
assert custom_event_found
156+
assert barrier_name_found
157+
158+
140159
@flaky(max_runs=3, min_passes=1)
141160
def test_script_job(job_name, capsys):
142161
job = create_script_job(PROJECT, REGION, job_name)
@@ -196,3 +215,9 @@ def test_pd_job(job_name, disk_name):
196215
additional_test=lambda: _check_policy(job, job_name, disk_names),
197216
region=region,
198217
)
218+
219+
220+
@flaky(max_runs=3, min_passes=1)
221+
def test_create_job_with_custom_events(job_name):
222+
job = create_job_with_status_events(PROJECT, REGION, job_name)
223+
_test_body(job, additional_test=lambda: _check_custom_events(job))

0 commit comments

Comments
 (0)