Skip to content

Commit 278d7e1

Browse files
authored
docs(samples): Adding samples for template usage (#41)
Preparing another code sample. This time for the [`Create a job from a Compute Engine instance template`](https://cloud.google.com/batch/docs/create-run-job#create-job-instance-template) section.
1 parent 8695e99 commit 278d7e1

File tree

3 files changed

+204
-2
lines changed

3 files changed

+204
-2
lines changed

compute/batch/requirements-test.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pytest==7.1.3
2-
pytest-parallel==0.1.1
3-
google-cloud-storage==2.5.0
2+
google-cloud-compute==1.5.2
3+
google-cloud-resource-manager==1.6.1
4+
google-cloud-storage==2.5.0
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
# [START batch_create_job_with_template]
16+
from google.cloud import batch_v1
17+
18+
19+
def create_script_job_with_template(project_id: str, region: str, job_name: str, template_link: str) -> batch_v1.Job:
20+
"""
21+
This method shows how to create a sample Batch Job that will run
22+
a simple command on Cloud Compute instances created using a provided Template.
23+
24+
Args:
25+
project_id: project ID or project number of the Cloud project you want to use.
26+
region: name of the region you want to use to run the job. Regions that are
27+
available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
28+
job_name: the name of the job that will be created.
29+
It needs to be unique for each project and region pair.
30+
template_link: a link to an existing Instance Template. Acceptable formats:
31+
* "projects/{project_id}/global/instanceTemplates/{template_name}"
32+
* "{template_name}" - if the template is defined in the same project as used to create the Job.
33+
34+
Returns:
35+
A job object representing the job created.
36+
"""
37+
client = batch_v1.BatchServiceClient()
38+
39+
# Define what will be done as part of the job.
40+
task = batch_v1.TaskSpec()
41+
runnable = batch_v1.Runnable()
42+
runnable.script = batch_v1.Runnable.Script()
43+
runnable.script.text = "echo Hello world! This is task ${BATCH_TASK_INDEX}. This job has a total of ${BATCH_TASK_COUNT} tasks."
44+
# You can also run a script from a file. Just remember, that needs to be a script that's
45+
# already on the VM that will be running the job. Using runnable.script.text and runnable.script.path is mutually
46+
# exclusive.
47+
# runnable.script.path = '/tmp/test.sh'
48+
task.runnables = [runnable]
49+
50+
# We can specify what resources are requested by each task.
51+
resources = batch_v1.ComputeResource()
52+
resources.cpu_milli = 2000 # in milliseconds per cpu-second. This means the task requires 2 whole CPUs.
53+
resources.memory_mib = 16
54+
task.compute_resource = resources
55+
56+
task.max_retry_count = 2
57+
task.max_run_duration = "3600s"
58+
59+
# Tasks are grouped inside a job using TaskGroups.
60+
group = batch_v1.TaskGroup()
61+
group.task_count = 4
62+
group.task_spec = task
63+
64+
# Policies are used to define on what kind of virtual machines the tasks will run on.
65+
# In this case, we tell the system to use an instance template that defines all the
66+
# required parameters.
67+
allocation_policy = batch_v1.AllocationPolicy()
68+
instances = batch_v1.AllocationPolicy.InstancePolicyOrTemplate()
69+
instances.instance_template = template_link
70+
allocation_policy.instances = [instances]
71+
72+
job = batch_v1.Job()
73+
job.task_groups = [group]
74+
job.allocation_policy = allocation_policy
75+
job.labels = {"env": "testing", "type": "script"}
76+
# We use Cloud Logging as it's an out of the box available option
77+
job.logs_policy = batch_v1.LogsPolicy()
78+
job.logs_policy.destination = batch_v1.LogsPolicy.Destination.CLOUD_LOGGING
79+
80+
create_request = batch_v1.CreateJobRequest()
81+
create_request.job = job
82+
create_request.job_id = job_name
83+
# The job's parent is the region in which the job will run
84+
create_request.parent = f"projects/{project_id}/locations/{region}"
85+
86+
return client.create_job(create_request)
87+
# [END batch_create_job_with_template]
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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+
import uuid
16+
17+
import google.auth
18+
from google.cloud import batch_v1
19+
from google.cloud import compute_v1
20+
from google.cloud import resourcemanager_v3
21+
import pytest
22+
23+
24+
from .test_basics import _test_body
25+
26+
from ..create.create_with_template import create_script_job_with_template
27+
28+
PROJECT = google.auth.default()[1]
29+
30+
PROJECT_NUMBER = resourcemanager_v3.ProjectsClient().get_project(name=f"projects/{PROJECT}").name.split("/")[1]
31+
32+
REGION = 'europe-north1'
33+
34+
TIMEOUT = 600 # 10 minutes
35+
36+
WAIT_STATES = {
37+
batch_v1.JobStatus.State.STATE_UNSPECIFIED,
38+
batch_v1.JobStatus.State.QUEUED,
39+
batch_v1.JobStatus.State.RUNNING,
40+
batch_v1.JobStatus.State.SCHEDULED,
41+
}
42+
43+
44+
@pytest.fixture
45+
def job_name():
46+
return f"test-job-{uuid.uuid4().hex[:10]}"
47+
48+
49+
@pytest.fixture
50+
def instance_template():
51+
disk = compute_v1.AttachedDisk()
52+
initialize_params = compute_v1.AttachedDiskInitializeParams()
53+
initialize_params.source_image = (
54+
"projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts"
55+
)
56+
initialize_params.disk_size_gb = 25
57+
initialize_params.disk_type = 'pd-balanced'
58+
disk.initialize_params = initialize_params
59+
disk.auto_delete = True
60+
disk.boot = True
61+
62+
network_interface = compute_v1.NetworkInterface()
63+
network_interface.name = "global/networks/default"
64+
65+
access = compute_v1.AccessConfig()
66+
access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
67+
access.name = "External NAT"
68+
access.network_tier = access.NetworkTier.PREMIUM.name
69+
network_interface.access_configs = [access]
70+
71+
template = compute_v1.InstanceTemplate()
72+
template.name = "test-template-" + uuid.uuid4().hex[:10]
73+
template.properties = compute_v1.InstanceProperties()
74+
template.properties.disks = [disk]
75+
template.properties.machine_type = "e2-standard-16"
76+
template.properties.network_interfaces = [network_interface]
77+
78+
template.properties.scheduling = compute_v1.Scheduling()
79+
template.properties.scheduling.on_host_maintenance = compute_v1.Scheduling.OnHostMaintenance.MIGRATE.name
80+
template.properties.scheduling.provisioning_model = compute_v1.Scheduling.ProvisioningModel.STANDARD.name
81+
template.properties.scheduling.automatic_restart = True
82+
83+
template.properties.service_accounts = [
84+
{
85+
"email": f"{PROJECT_NUMBER}[email protected]",
86+
"scopes": [
87+
"https://www.googleapis.com/auth/devstorage.read_only",
88+
"https://www.googleapis.com/auth/logging.write",
89+
"https://www.googleapis.com/auth/monitoring.write",
90+
"https://www.googleapis.com/auth/servicecontrol",
91+
"https://www.googleapis.com/auth/service.management.readonly",
92+
"https://www.googleapis.com/auth/trace.append"
93+
]
94+
}
95+
]
96+
97+
template_client = compute_v1.InstanceTemplatesClient()
98+
operation_client = compute_v1.GlobalOperationsClient()
99+
op = template_client.insert_unary(
100+
project=PROJECT, instance_template_resource=template
101+
)
102+
operation_client.wait(project=PROJECT, operation=op.name)
103+
104+
template = template_client.get(project=PROJECT, instance_template=template.name)
105+
106+
yield template
107+
108+
op = template_client.delete_unary(project=PROJECT, instance_template=template.name)
109+
operation_client.wait(project=PROJECT, operation=op.name)
110+
111+
112+
def test_template_job(job_name, instance_template):
113+
job = create_script_job_with_template(PROJECT, REGION, job_name, instance_template.self_link)
114+
_test_body(job)

0 commit comments

Comments
 (0)