From 4e46538dfaa221f2358f40450a4579dc9064cca0 Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 18 Oct 2021 15:00:29 +0200 Subject: [PATCH 1/9] chore(docs): Instance template creation samples --- samples/snippets/sample_templates.py | 141 +++++++++++++++++++++ samples/snippets/test_sample_start_stop.py | 3 +- samples/snippets/test_sample_templates.py | 74 +++++++++++ 3 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 samples/snippets/sample_templates.py create mode 100644 samples/snippets/test_sample_templates.py diff --git a/samples/snippets/sample_templates.py b/samples/snippets/sample_templates.py new file mode 100644 index 000000000..714777cdb --- /dev/null +++ b/samples/snippets/sample_templates.py @@ -0,0 +1,141 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Iterable + +from google.cloud import compute_v1 + + +def get_instance_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: + template_client = compute_v1.InstanceTemplatesClient() + return template_client.get(project=project_id, instance_template=template_name) + + +def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemplate]: + template_client = compute_v1.InstanceTemplatesClient() + return template_client.list(project=project_id) + + +def create_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: + + # Describe the size and source image of the boot disk to attach to the instance. + disk = compute_v1.AttachedDisk() + initialize_params = compute_v1.AttachedDiskInitializeParams() + initialize_params.source_image = ( + "projects/debian-cloud/global/images/family/debian-11" + ) + initialize_params.disk_size_gb = 250 + disk.initialize_params = initialize_params + disk.auto_delete = True + disk.boot = True + + # Use the default network, without specifying a subnetwork. + network_interface = compute_v1.NetworkInterface() + network_interface.name = "global/networks/default" + + # Let the instance have external IP + network_interface.access_configs = [compute_v1.AccessConfig()] + network_interface.access_configs[0].name = "External NAT" + network_interface.access_configs[0].type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT + network_interface.access_configs[0].network_tier = ( + compute_v1.AccessConfig.NetworkTier.PREMIUM + ) + + template = compute_v1.InstanceTemplate() + template.name = template_name + template.properties.disks = [disk] + template.properties.machine_type = "e2-standard-4" + template.properties.network_interfaces = [network_interface] + + template_client = compute_v1.InstanceTemplatesClient() + operation_client = compute_v1.GlobalOperationsClient() + op = template_client.insert(project=project_id, instance_template_resource=template) + operation_client.wait(project=project_id, operation=op.name) + + return template_client.get(project=project_id, instance_template=template_name) + + +def create_template_from_instance( + project_id: str, instance_link: str, template_name: str +) -> compute_v1.InstanceTemplate: + + disk = compute_v1.DiskInstantiationConfig() + # This name must match the name of a disk attached to the instance you are + # basing your template on. + disk.device_name = "disk-1" + # Replace the original disk image used in your instance with a Rocky Linux image. + disk.instantiate_from = ( + compute_v1.DiskInstantiationConfig.InstantiateFrom.CUSTOM_IMAGE + ) + disk.custom_image = "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" + # You can override the auto_delete setting. + disk.auto_delete = True + + template = compute_v1.InstanceTemplate() + template.name = template_name + template.source_instance = instance_link + template.source_instance_params = compute_v1.SourceInstanceParams() + template.source_instance_params.disk_configs = [disk] + + template_client = compute_v1.InstanceTemplatesClient() + operation_client = compute_v1.GlobalOperationsClient() + op = template_client.insert(project=project_id, instance_template_resource=template) + operation_client.wait(project=project_id, operation=op.name) + + return template_client.get(project=project_id, instance_template=template_name) + + +def create_template_with_subnet( + project_id: str, network: str, subnetwork: str, template_name: str +) -> compute_v1.InstanceTemplate: + """ + Create an instance template that will use a provided subnet. + + """ + # Describe the size and source image of the boot disk to attach to the instance. + disk = compute_v1.AttachedDisk() + initialize_params = compute_v1.AttachedDiskInitializeParams() + initialize_params.source_image = ( + "projects/debian-cloud/global/images/family/debian-11" + ) + initialize_params.disk_size_gb = 250 + disk.initialize_params = initialize_params + disk.auto_delete = True + disk.boot = True + + template = compute_v1.InstanceTemplate() + template.name = template_name + template.properties = compute_v1.InstanceProperties() + template.properties.disks = [disk] + template.properties.machine_type = "e2-standard-4" + + # Make this template use provided subnetwork. + network_interface = compute_v1.NetworkInterface() + network_interface.network = network + network_interface.subnetwork = subnetwork + template.properties.network_interfaces = [network_interface] + + template_client = compute_v1.InstanceTemplatesClient() + operation_client = compute_v1.GlobalOperationsClient() + op = template_client.insert(project=project_id, instance_template_resource=template) + operation_client.wait(project=project_id, operation=op.name) + + return template_client.get(project=project_id, instance_template=template_name) + + +def delete_instance_template(project_id: str, template_name: str): + template_client = compute_v1.InstanceTemplatesClient() + operation_client = compute_v1.GlobalOperationsClient() + op = template_client.delete(project=project_id, instance_template=template_name) + operation_client.wait(project=project_id, operation=op.name) + return diff --git a/samples/snippets/test_sample_start_stop.py b/samples/snippets/test_sample_start_stop.py index a2f2bf377..2d6aac5c2 100644 --- a/samples/snippets/test_sample_start_stop.py +++ b/samples/snippets/test_sample_start_stop.py @@ -22,7 +22,7 @@ import pytest -from samples.snippets.sample_start_stop import start_instance, start_instance_with_encryption_key, stop_instance +from sample_start_stop import start_instance, start_instance_with_encryption_key, stop_instance PROJECT = google.auth.default()[1] @@ -43,6 +43,7 @@ def _make_disk(raw_key: bytes = None): disk.auto_delete = True disk.boot = True disk.type_ = compute_v1.AttachedDisk.Type.PERSISTENT + disk.device_name = 'disk-1' if raw_key: disk.disk_encryption_key = compute_v1.CustomerEncryptionKey() diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py new file mode 100644 index 000000000..ea46866a3 --- /dev/null +++ b/samples/snippets/test_sample_templates.py @@ -0,0 +1,74 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest +import uuid + +import google.auth +from google.cloud import compute_v1 + +from sample_templates import ( + create_template, + create_template_from_instance, + create_template_with_subnet, + delete_instance_template, + get_instance_template, + list_instance_templates +) + +from test_sample_start_stop import compute_instance + +PROJECT = google.auth.default()[1] + +INSTANCE_ZONE = "europe-central2-b" + + +def test_create_instance(): + template_name = "i" + uuid.uuid4().hex[:10] + template = create_template(PROJECT, template_name) + + try: + assert template.name == template_name + assert template.properties.disks[0].initialize_params.disk_size_gb == 250 + assert 'debian-11' in template.properties.disks[0].initialize_params.source_image + assert template.properties.network_interfaces[0].name == "global/networks/default" + assert template.properties.machine_type == "e2-standard-4" + finally: + delete_instance_template(PROJECT, template_name) + assert all(template.name != template_name for template in list_instance_templates(PROJECT)) + + +def test_create_from_instance(compute_instance): + template_name = "i" + uuid.uuid4().hex[:10] + template = create_template_from_instance(PROJECT, compute_instance.self_link, template_name) + + try: + assert template.name == template_name + assert template.properties.machine_type in compute_instance.machine_type + assert template.properties.disks[0].disk_size_gb == compute_instance.disks[0].disk_size_gb + assert template.properties.disks[0].initialize_params.source_image == "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" + finally: + delete_instance_template(PROJECT, template_name) + + +def test_create_template_with_subnet(): + template_name = "i" + uuid.uuid4().hex[:10] + template = create_template_with_subnet(PROJECT, 'global/networks/default', 'regions/asia-east1/subnetworks/default', template_name) + + try: + assert template.name == template_name + assert 'global/networks/default' in template.properties.network_interfaces[0].network + assert 'regions/asia-east1/subnetworks/default' in template.properties.network_interfaces[0].subnetwork + finally: + delete_instance_template(PROJECT, template_name) From 35be7ec5ae62a812ed72d501eb77b79fb6fd04f1 Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Tue, 19 Oct 2021 16:06:47 +0200 Subject: [PATCH 2/9] chore(docs): Adding docstrings. --- samples/snippets/sample_templates.py | 62 +++++++++++++++++++++-- samples/snippets/test_sample_templates.py | 50 +++++++++++++----- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/samples/snippets/sample_templates.py b/samples/snippets/sample_templates.py index 714777cdb..d8e8f5042 100644 --- a/samples/snippets/sample_templates.py +++ b/samples/snippets/sample_templates.py @@ -17,17 +17,45 @@ def get_instance_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: + """ + Retrieve information about given instance template. + + Args: + project_id: project ID or project number of the Cloud project you use. + template_name: name of the template you want to get. + + Returns: + InstanceTemplate object containing information about given template. + """ template_client = compute_v1.InstanceTemplatesClient() return template_client.get(project=project_id, instance_template=template_name) def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemplate]: + """ + Get a list of InstanceTemplate objects available in given project. + + Args: + project_id: project ID or project number of the Cloud project you use. + + Returns: + Iterable list of InstanceTemplate objects. + """ template_client = compute_v1.InstanceTemplatesClient() return template_client.list(project=project_id) def create_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: + """ + Create a new template in given project with provided name. + + Args: + project_id: project ID or project number of the Cloud project you use. + template_name: name of the new template that is created. + Returns: + InstanceTemplate object describing the new instance template. + """ # Describe the size and source image of the boot disk to attach to the instance. disk = compute_v1.AttachedDisk() initialize_params = compute_v1.AttachedDiskInitializeParams() @@ -65,10 +93,19 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT return template_client.get(project=project_id, instance_template=template_name) -def create_template_from_instance( - project_id: str, instance_link: str, template_name: str -) -> compute_v1.InstanceTemplate: +def create_template_from_instance(project_id: str, instance: str, template_name: str) -> compute_v1.InstanceTemplate: + """ + Create a new instance template based on an existing instance. + Args: + project_id: project ID or project number of the Cloud project you use. + instance: the instance the new template will be based on. This value uses + the following format: "projects/{project}/zones/{zone}/instances/{instance_name}" + template_name: name of the new template that is created. + + Returns: + InstanceTemplate object describing the new instance template. + """ disk = compute_v1.DiskInstantiationConfig() # This name must match the name of a disk attached to the instance you are # basing your template on. @@ -83,7 +120,7 @@ def create_template_from_instance( template = compute_v1.InstanceTemplate() template.name = template_name - template.source_instance = instance_link + template.source_instance = instance template.source_instance_params = compute_v1.SourceInstanceParams() template.source_instance_params.disk_configs = [disk] @@ -101,6 +138,16 @@ def create_template_with_subnet( """ Create an instance template that will use a provided subnet. + Args: + project_id: project ID or project number of the Cloud project you use. + network: the network to be used in the new template. This value uses + the following format: "projects/{project}/global/networks/{network}" + subnetwork: the subnetwork to be used in the new template. This value + uses the following format: "projects/{project}/regions/{region}/subnetworks/{subnetwork}" + template_name: name of the new template that is created. + + Returns: + InstanceTemplate object describing the new instance template. """ # Describe the size and source image of the boot disk to attach to the instance. disk = compute_v1.AttachedDisk() @@ -134,6 +181,13 @@ def create_template_with_subnet( def delete_instance_template(project_id: str, template_name: str): + """ + Delete an instance template. + + Args: + project_id: project ID or project number of the Cloud project you use. + template_name: name of the new template to delete. + """ template_client = compute_v1.InstanceTemplatesClient() operation_client = compute_v1.GlobalOperationsClient() op = template_client.delete(project=project_id, instance_template=template_name) diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py index ea46866a3..c29ee3584 100644 --- a/samples/snippets/test_sample_templates.py +++ b/samples/snippets/test_sample_templates.py @@ -12,22 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest import uuid import google.auth -from google.cloud import compute_v1 from sample_templates import ( create_template, create_template_from_instance, create_template_with_subnet, delete_instance_template, - get_instance_template, - list_instance_templates + list_instance_templates, ) from test_sample_start_stop import compute_instance +# Needed to make the flake8 happy. +assert compute_instance PROJECT = google.auth.default()[1] @@ -41,34 +40,59 @@ def test_create_instance(): try: assert template.name == template_name assert template.properties.disks[0].initialize_params.disk_size_gb == 250 - assert 'debian-11' in template.properties.disks[0].initialize_params.source_image - assert template.properties.network_interfaces[0].name == "global/networks/default" + assert ( + "debian-11" in template.properties.disks[0].initialize_params.source_image + ) + assert ( + template.properties.network_interfaces[0].name == "global/networks/default" + ) assert template.properties.machine_type == "e2-standard-4" finally: delete_instance_template(PROJECT, template_name) - assert all(template.name != template_name for template in list_instance_templates(PROJECT)) + assert all( + template.name != template_name for template in list_instance_templates(PROJECT) + ) def test_create_from_instance(compute_instance): template_name = "i" + uuid.uuid4().hex[:10] - template = create_template_from_instance(PROJECT, compute_instance.self_link, template_name) + template = create_template_from_instance( + PROJECT, compute_instance.self_link, template_name + ) try: assert template.name == template_name assert template.properties.machine_type in compute_instance.machine_type - assert template.properties.disks[0].disk_size_gb == compute_instance.disks[0].disk_size_gb - assert template.properties.disks[0].initialize_params.source_image == "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" + assert ( + template.properties.disks[0].disk_size_gb + == compute_instance.disks[0].disk_size_gb + ) + assert ( + template.properties.disks[0].initialize_params.source_image + == "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" + ) finally: delete_instance_template(PROJECT, template_name) def test_create_template_with_subnet(): template_name = "i" + uuid.uuid4().hex[:10] - template = create_template_with_subnet(PROJECT, 'global/networks/default', 'regions/asia-east1/subnetworks/default', template_name) + template = create_template_with_subnet( + PROJECT, + "global/networks/default", + "regions/asia-east1/subnetworks/default", + template_name, + ) try: assert template.name == template_name - assert 'global/networks/default' in template.properties.network_interfaces[0].network - assert 'regions/asia-east1/subnetworks/default' in template.properties.network_interfaces[0].subnetwork + assert ( + "global/networks/default" + in template.properties.network_interfaces[0].network + ) + assert ( + "regions/asia-east1/subnetworks/default" + in template.properties.network_interfaces[0].subnetwork + ) finally: delete_instance_template(PROJECT, template_name) From ee4d8ae3e91be918f673097726cd78003e4c2e07 Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Thu, 21 Oct 2021 15:58:34 +0200 Subject: [PATCH 3/9] chore(docs): Applying suggested changes. --- samples/snippets/sample_templates.py | 50 ++++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/samples/snippets/sample_templates.py b/samples/snippets/sample_templates.py index d8e8f5042..a099a9e96 100644 --- a/samples/snippets/sample_templates.py +++ b/samples/snippets/sample_templates.py @@ -18,14 +18,15 @@ def get_instance_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: """ - Retrieve information about given instance template. + Retrieve an instance template, which you can use to create virtual machine + (VM) instances and managed instance groups (MIGs). Args: project_id: project ID or project number of the Cloud project you use. - template_name: name of the template you want to get. + template_name: name of the template to retrieve. Returns: - InstanceTemplate object containing information about given template. + InstanceTemplate object that represents the retrieved template. """ template_client = compute_v1.InstanceTemplatesClient() return template_client.get(project=project_id, instance_template=template_name) @@ -33,7 +34,7 @@ def get_instance_template(project_id: str, template_name: str) -> compute_v1.Ins def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemplate]: """ - Get a list of InstanceTemplate objects available in given project. + Get a list of InstanceTemplate objects available in a project. Args: project_id: project ID or project number of the Cloud project you use. @@ -47,16 +48,18 @@ def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemp def create_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: """ - Create a new template in given project with provided name. + Create a new instance template with the provided name and a specific + instance configuration. Args: project_id: project ID or project number of the Cloud project you use. - template_name: name of the new template that is created. + template_name: name of the new template to create. Returns: - InstanceTemplate object describing the new instance template. + InstanceTemplate object that represents the new instance template. """ - # Describe the size and source image of the boot disk to attach to the instance. + # The template describes the size and source image of the boot disk + # to attach to the instance. disk = compute_v1.AttachedDisk() initialize_params = compute_v1.AttachedDiskInitializeParams() initialize_params.source_image = ( @@ -67,11 +70,12 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT disk.auto_delete = True disk.boot = True - # Use the default network, without specifying a subnetwork. + # The template connects the instance to the `default` network, + # without specifying a subnetwork. network_interface = compute_v1.NetworkInterface() network_interface.name = "global/networks/default" - # Let the instance have external IP + # The template lets the instance use an external IP address. network_interface.access_configs = [compute_v1.AccessConfig()] network_interface.access_configs[0].name = "External NAT" network_interface.access_configs[0].type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT @@ -96,26 +100,27 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT def create_template_from_instance(project_id: str, instance: str, template_name: str) -> compute_v1.InstanceTemplate: """ Create a new instance template based on an existing instance. + This new template specifies a different boot disk. Args: project_id: project ID or project number of the Cloud project you use. - instance: the instance the new template will be based on. This value uses + instance: the instance to base the new template on. This value uses the following format: "projects/{project}/zones/{zone}/instances/{instance_name}" - template_name: name of the new template that is created. + template_name: name of the new template to create. Returns: - InstanceTemplate object describing the new instance template. + InstanceTemplate object that represents the new instance template. """ disk = compute_v1.DiskInstantiationConfig() - # This name must match the name of a disk attached to the instance you are + # Device name must match the name of a disk attached to the instance you are # basing your template on. disk.device_name = "disk-1" - # Replace the original disk image used in your instance with a Rocky Linux image. + # Replace the original boot disk image used in your instance with a Rocky Linux image. disk.instantiate_from = ( compute_v1.DiskInstantiationConfig.InstantiateFrom.CUSTOM_IMAGE ) disk.custom_image = "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" - # You can override the auto_delete setting. + # Override the auto_delete setting. disk.auto_delete = True template = compute_v1.InstanceTemplate() @@ -136,7 +141,7 @@ def create_template_with_subnet( project_id: str, network: str, subnetwork: str, template_name: str ) -> compute_v1.InstanceTemplate: """ - Create an instance template that will use a provided subnet. + Create an instance template that uses a provided subnet. Args: project_id: project ID or project number of the Cloud project you use. @@ -144,12 +149,13 @@ def create_template_with_subnet( the following format: "projects/{project}/global/networks/{network}" subnetwork: the subnetwork to be used in the new template. This value uses the following format: "projects/{project}/regions/{region}/subnetworks/{subnetwork}" - template_name: name of the new template that is created. + template_name: name of the new template to create. Returns: - InstanceTemplate object describing the new instance template. + InstanceTemplate object that represents the new instance template. """ - # Describe the size and source image of the boot disk to attach to the instance. + # The template describes the size and source image of the book disk to + # attach to the instance. disk = compute_v1.AttachedDisk() initialize_params = compute_v1.AttachedDiskInitializeParams() initialize_params.source_image = ( @@ -166,7 +172,7 @@ def create_template_with_subnet( template.properties.disks = [disk] template.properties.machine_type = "e2-standard-4" - # Make this template use provided subnetwork. + # The template connects the instance to the specified network and subnetwork. network_interface = compute_v1.NetworkInterface() network_interface.network = network network_interface.subnetwork = subnetwork @@ -186,7 +192,7 @@ def delete_instance_template(project_id: str, template_name: str): Args: project_id: project ID or project number of the Cloud project you use. - template_name: name of the new template to delete. + template_name: name of the template to delete. """ template_client = compute_v1.InstanceTemplatesClient() operation_client = compute_v1.GlobalOperationsClient() From 41512b9ccfc26d976aef0e2d77c4485fc8bfeb44 Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Thu, 21 Oct 2021 16:55:54 +0200 Subject: [PATCH 4/9] chore(docs): Trying to fix test errors. --- samples/snippets/test_sample_create_vm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/snippets/test_sample_create_vm.py b/samples/snippets/test_sample_create_vm.py index b69570f16..536425d67 100644 --- a/samples/snippets/test_sample_create_vm.py +++ b/samples/snippets/test_sample_create_vm.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import time import uuid import google.auth @@ -107,7 +108,9 @@ def subnetwork(): op = network_client.insert(project=PROJECT, network_resource=network) wait_for_operation(op, PROJECT) network = network_client.get(project=PROJECT, network=network.name) - + # Was getting some "resource not ready" errors, so let's see if giving more + # time will make them go away. + time.sleep(5) subnet = compute_v1.Subnetwork() subnet.name = "test-subnet-" + uuid.uuid4().hex[:10] subnet.network = network_client.get(project=PROJECT, network=network.name).self_link From a41ee9516b1c73bc9d4d1c07bf37050e3cf9c65f Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 8 Nov 2021 17:15:58 +0100 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> --- samples/snippets/test_sample_templates.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py index c29ee3584..0d476c830 100644 --- a/samples/snippets/test_sample_templates.py +++ b/samples/snippets/test_sample_templates.py @@ -24,9 +24,7 @@ list_instance_templates, ) -from test_sample_start_stop import compute_instance -# Needed to make the flake8 happy. -assert compute_instance +from test_sample_start_stop import compute_instance # noqa: F401 PROJECT = google.auth.default()[1] From deffb614a2a38c9f12b90f72513e37fd40177deb Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 8 Nov 2021 17:16:49 +0100 Subject: [PATCH 6/9] chore(docs): Applying changes from review. --- samples/snippets/sample_templates.py | 40 +++++++++++++++++++---- samples/snippets/test_sample_templates.py | 6 ++-- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/samples/snippets/sample_templates.py b/samples/snippets/sample_templates.py index a099a9e96..f6a0280f9 100644 --- a/samples/snippets/sample_templates.py +++ b/samples/snippets/sample_templates.py @@ -11,11 +11,27 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Iterable +# [START compute_template_list ] +from typing import Iterable +# [END compute_template_list ] + +# [START compute_template_create ] +# [START compute_template_list ] +# [START compute_template_get ] +# [START compute_template_create_from_instance ] +# [START compute_template_create_with_subnet ] +# [START compute_template_delete ] from google.cloud import compute_v1 +# [END compute_template_delete ] +# [END compute_template_create_with_subnet ] +# [END compute_template_create_from_instance ] +# [END compute_template_get ] +# [END compute_template_list ] +# [END compute_template_create ] +# [START compute_template_get ] def get_instance_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: """ Retrieve an instance template, which you can use to create virtual machine @@ -30,8 +46,10 @@ def get_instance_template(project_id: str, template_name: str) -> compute_v1.Ins """ template_client = compute_v1.InstanceTemplatesClient() return template_client.get(project=project_id, instance_template=template_name) +# [END compute_template_get ] +# [START compute_template_list ] def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemplate]: """ Get a list of InstanceTemplate objects available in a project. @@ -44,8 +62,9 @@ def list_instance_templates(project_id: str) -> Iterable[compute_v1.InstanceTemp """ template_client = compute_v1.InstanceTemplatesClient() return template_client.list(project=project_id) +# [END compute_template_list ] - +# [START compute_template_create ] def create_template(project_id: str, template_name: str) -> compute_v1.InstanceTemplate: """ Create a new instance template with the provided name and a specific @@ -76,12 +95,13 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT network_interface.name = "global/networks/default" # The template lets the instance use an external IP address. - network_interface.access_configs = [compute_v1.AccessConfig()] - network_interface.access_configs[0].name = "External NAT" - network_interface.access_configs[0].type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT - network_interface.access_configs[0].network_tier = ( + access_config = compute_v1.AccessConfig() + access_config.name = "External NAT" + access_config.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT + access_config.network_tier = ( compute_v1.AccessConfig.NetworkTier.PREMIUM ) + network_interface.access_configs = [access_config] template = compute_v1.InstanceTemplate() template.name = template_name @@ -95,8 +115,10 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT operation_client.wait(project=project_id, operation=op.name) return template_client.get(project=project_id, instance_template=template_name) +# [START compute_template_create ] +# [START compute_template_create_from_instance ] def create_template_from_instance(project_id: str, instance: str, template_name: str) -> compute_v1.InstanceTemplate: """ Create a new instance template based on an existing instance. @@ -135,8 +157,10 @@ def create_template_from_instance(project_id: str, instance: str, template_name: operation_client.wait(project=project_id, operation=op.name) return template_client.get(project=project_id, instance_template=template_name) +# [END compute_template_create_from_instance ] +# [START compute_template_create_with_subnet ] def create_template_with_subnet( project_id: str, network: str, subnetwork: str, template_name: str ) -> compute_v1.InstanceTemplate: @@ -184,8 +208,9 @@ def create_template_with_subnet( operation_client.wait(project=project_id, operation=op.name) return template_client.get(project=project_id, instance_template=template_name) +# [END compute_template_create_with_subnet ] - +# [START compute_template_delete ] def delete_instance_template(project_id: str, template_name: str): """ Delete an instance template. @@ -199,3 +224,4 @@ def delete_instance_template(project_id: str, template_name: str): op = template_client.delete(project=project_id, instance_template=template_name) operation_client.wait(project=project_id, operation=op.name) return +# [END compute_template_delete ] diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py index c29ee3584..fea2060d4 100644 --- a/samples/snippets/test_sample_templates.py +++ b/samples/snippets/test_sample_templates.py @@ -24,9 +24,9 @@ list_instance_templates, ) -from test_sample_start_stop import compute_instance -# Needed to make the flake8 happy. -assert compute_instance +# Turning off F401 check because flake8 doesn't recognize using +# PyTest fixture as parameter as usage. +from test_sample_start_stop import compute_instance # noqa: F401 PROJECT = google.auth.default()[1] From fe3d9841350b873c31357cf5cccd0b0d4226ebb5 Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 8 Nov 2021 17:20:50 +0100 Subject: [PATCH 7/9] chore(docs): Fixing region tag. --- samples/snippets/sample_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/snippets/sample_templates.py b/samples/snippets/sample_templates.py index 53f1b65d1..99bf5bdd5 100644 --- a/samples/snippets/sample_templates.py +++ b/samples/snippets/sample_templates.py @@ -116,7 +116,7 @@ def create_template(project_id: str, template_name: str) -> compute_v1.InstanceT operation_client.wait(project=project_id, operation=op.name) return template_client.get(project=project_id, instance_template=template_name) -# [START compute_template_create ] +# [END compute_template_create ] # [START compute_template_create_from_instance ] From 80bb1d855a00bef4e30ddd44f5a919445b177fdf Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 15 Nov 2021 13:23:44 +0100 Subject: [PATCH 8/9] chore(samples): Updating tests according to review. --- samples/snippets/test_sample_templates.py | 109 ++++++++++++---------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py index bfc2ddc2a..f21fc3e76 100644 --- a/samples/snippets/test_sample_templates.py +++ b/samples/snippets/test_sample_templates.py @@ -15,6 +15,7 @@ import uuid import google.auth +import pytest from sample_templates import ( create_template, @@ -26,73 +27,83 @@ # Turning off F401 check because flake8 doesn't recognize using # PyTest fixture as parameter as usage. -from test_sample_start_stop import compute_instance # noqa: F401 +# Uncomment this import if you want to run test from only this file. +# from test_sample_start_stop import compute_instance # noqa: F401 PROJECT = google.auth.default()[1] INSTANCE_ZONE = "europe-central2-b" -def test_create_instance(): +@pytest.fixture +def deletable_template_name(): + template_name = "i" + uuid.uuid4().hex[:10] + yield template_name + delete_instance_template(PROJECT, template_name) + + +@pytest.fixture +def template_to_be_deleted(): template_name = "i" + uuid.uuid4().hex[:10] template = create_template(PROJECT, template_name) + yield template - try: - assert template.name == template_name - assert template.properties.disks[0].initialize_params.disk_size_gb == 250 - assert ( - "debian-11" in template.properties.disks[0].initialize_params.source_image - ) - assert ( - template.properties.network_interfaces[0].name == "global/networks/default" - ) - assert template.properties.machine_type == "e2-standard-4" - finally: - delete_instance_template(PROJECT, template_name) - assert all( - template.name != template_name for template in list_instance_templates(PROJECT) + +def test_create_template_and_list(deletable_template_name): + + template = create_template(PROJECT, deletable_template_name) + + assert template.name == deletable_template_name + assert any( + template.name == deletable_template_name + for template in list_instance_templates(PROJECT) ) + assert template.properties.disks[0].initialize_params.disk_size_gb == 250 + assert "debian-11" in template.properties.disks[0].initialize_params.source_image + assert template.properties.network_interfaces[0].name == "global/networks/default" + assert template.properties.machine_type == "e2-standard-4" -def test_create_from_instance(compute_instance): # noqa: F811 - template_name = "i" + uuid.uuid4().hex[:10] +def test_create_from_instance(compute_instance, deletable_template_name): # noqa: F811 + template = create_template_from_instance( - PROJECT, compute_instance.self_link, template_name + PROJECT, compute_instance.self_link, deletable_template_name ) - try: - assert template.name == template_name - assert template.properties.machine_type in compute_instance.machine_type - assert ( - template.properties.disks[0].disk_size_gb - == compute_instance.disks[0].disk_size_gb - ) - assert ( - template.properties.disks[0].initialize_params.source_image - == "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" - ) - finally: - delete_instance_template(PROJECT, template_name) - - -def test_create_template_with_subnet(): - template_name = "i" + uuid.uuid4().hex[:10] + assert template.name == deletable_template_name + assert template.properties.machine_type in compute_instance.machine_type + assert ( + template.properties.disks[0].disk_size_gb + == compute_instance.disks[0].disk_size_gb + ) + assert ( + template.properties.disks[0].initialize_params.source_image + == "projects/rocky-linux-cloud/global/images/family/rocky-linux-8" + ) + + +def test_create_template_with_subnet(deletable_template_name): template = create_template_with_subnet( PROJECT, "global/networks/default", "regions/asia-east1/subnetworks/default", - template_name, + deletable_template_name, + ) + + assert template.name == deletable_template_name + assert ( + "global/networks/default" in template.properties.network_interfaces[0].network ) + assert ( + "regions/asia-east1/subnetworks/default" + in template.properties.network_interfaces[0].subnetwork + ) + + +def test_delete_template(template_to_be_deleted): + delete_instance_template(PROJECT, template_to_be_deleted.name) - try: - assert template.name == template_name - assert ( - "global/networks/default" - in template.properties.network_interfaces[0].network - ) - assert ( - "regions/asia-east1/subnetworks/default" - in template.properties.network_interfaces[0].subnetwork - ) - finally: - delete_instance_template(PROJECT, template_name) + assert all( + template.name != template_to_be_deleted.name + for template in list_instance_templates(PROJECT) + ) From c6993cfe4265ba8cc98862071b6920599eb7405e Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Mon, 15 Nov 2021 14:08:57 +0100 Subject: [PATCH 9/9] chore(samples): Fixing the fixture import for tests to work. --- samples/snippets/test_sample_templates.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/samples/snippets/test_sample_templates.py b/samples/snippets/test_sample_templates.py index f21fc3e76..2c60aaafb 100644 --- a/samples/snippets/test_sample_templates.py +++ b/samples/snippets/test_sample_templates.py @@ -27,8 +27,7 @@ # Turning off F401 check because flake8 doesn't recognize using # PyTest fixture as parameter as usage. -# Uncomment this import if you want to run test from only this file. -# from test_sample_start_stop import compute_instance # noqa: F401 +from test_sample_start_stop import compute_instance # noqa: F401 PROJECT = google.auth.default()[1]