8000 Adding code samples to repository and nox. by m-strzelczyk · Pull Request #54 · googleapis/python-compute · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Dec 31, 2023. It is now read-only.

Adding code samples to repository and nox. #54

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
* @googleapis/yoshi-python


/samples/ @googleapis/python-samples-owners < 8000 path d="M4.25 7.25a.75.75 0 0 0 0 1.5h7.5a.75.75 0 0 0 0-1.5h-7.5Z">
/samples/ m-strzelczyk @googleapis/python-samples-owners
18 changes: 18 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ Build the docs via:

$ nox -s docs

*************************
Samples and code snippets
*************************

Code samples and snippets live in the `samples/` catalogue. Feel free to
provide more examples, but make sure to write tests for those examples.

The tests will run against a real Google Cloud Project, so you should
configure them just like the System Tests.

- To run sample tests, you can execute::

# Run all system tests
$ nox -s samples-3.8

# Run a single sample test
$ nox -s system-3.8 -- -k <name of test>

********************************************
Note About ``README`` as it pertains to PyPI
8000 ********************************************
Expand Down
24 changes: 22 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@


BLACK_VERSION = "black==19.10b0"
BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"]
BLACK_PATHS = ["docs", "google", "samples", "tests", "noxfile.py", "setup.py"]

DEFAULT_PYTHON_VERSION = "3.8"
SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"]
UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"]
SAMPLE_TEST_PYTHON_VERSIONS = ["3.8", "3.9"]

CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute()

Expand Down Expand Up @@ -59,7 +60,7 @@ def lint(session):
session.run(
"black", "--check", *BLACK_PATHS,
)
session.run("flake8", "google", "tests")
session.run("flake8", "google", "tests", "samples")


@nox.session(python=DEFAULT_PYTHON_VERSION)
Expand Down Expand Up @@ -112,6 +113,25 @@ def unit(session):
default(session)


@nox.session(python=SAMPLE_TEST_PYTHON_VERSIONS)
def samples(session):
"""Run tests for samples"""
samples_test_folder_path = CURRENT_DIRECTORY / "samples"
requirements_path = (
CURRENT_DIRECTORY / "samples" / "snippets" / "requirements-test.txt"
)

if not samples_test_folder_path.is_dir():
session.skip("Sample tests not found.")
return

session.install("-U", "pip", "setuptools")
session.install("-Ur", str(requirements_path))
session.install("-e", ".")

session.run("py.test", "--quiet", str(samples_test_folder_path), *session.posargs)


@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS)
def system(session):
"""Run the system test suite."""
Expand Down
38 changes: 38 additions & 0 deletions samples/snippets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# google-cloud-compute library samples

These samples demonstrate usage of the google-cloud-compute library to interact
with the Google Compute Engine API.

## Running the quickstart script

### Before you begin

1. If you haven't already, set up a Python Development Environment by following the [python setup guide](https://cloud.google.com/python/setup) and
[create a project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).

1. Create a service account with the 'Editor' permissions by following these
[instructions](https://cloud.google.com/iam/docs/creating-managing-service-accounts).

1. [Download a JSON key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) to use to authenticate your script.

1. Configure your local environment to use the acquired key.
```bash
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
```

### Install requirements

Create a new virtual environment and install the required libraries.
```bash
virtualenv --python python3 name-of-your-virtualenv
source name-of-your-virtualenv/bin/activate
pip install -r requirements.txt
```

### Run the demo

Run the quickstart script, providing it with your project name, a GCP zone and a name for the instance that will be created and destroyed:
```bash
# For example, to create machine "test-instance" in europe-central2-a in project "my-test-project":
python quickstart.py my-test-project europe-central2-a test-instance
```
246 changes: 246 additions & 0 deletions samples/snippets/quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
#!/usr/bin/env python

# 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.
"""
A sample script showing how to create, list and delete Google Compute Engine
instances using the google-cloud-compute library. It can be run from command
line to create, list and delete an instance in a given project in a given zone.
"""

import argparse

# [START compute_instances_list]
# [START compute_instances_list_all]
# [START compute_instances_create]
# [START compute_instances_delete]
# [START compute_instances_operation_check]
import typing

import google.cloud.compute_v1 as gce

# [END compute_instances_operation_check]
# [END compute_instances_delete]
# [END compute_instances_create]
# [END compute_instances_list_all]
# [END compute_instances_list]


# [START compute_instances_list]
def list_instances(project: str, zone: str) -> typing.Iterable[gce.Instance]:
"""
Gets a list of instances created in given project in given zone.
Returns an iterable collection of Instance objects.

Args:
project: Name of the project you want to use.
zone: Name of the zone you want to check, for example: us-west3-b

Returns:
An iterable collection of Instance objects.
"""
instance_client = gce.InstancesClient()
instance_list = instance_client.list(project=project, zone=zone)
return instance_list


# [END compute_instances_list]


# [START compute_instances_list_all]
def list_all_instances(project: str) -> typing.Dict[str, typing.Iterable[gce.Instance]]:
"""
Returns a dictionary of all instances present in a project, grouped by their zone.

Args:
project: Name of the project you want to use.

Returns:
A dictionary with zone names as keys (in form of "zones/{zone_name}") and
iterable collections of Instance objects as values.
"""
instance_client = gce.InstancesClient()
agg_list = instance_client.aggregated_list(project=project)
all_instances = {}
for zone, response in agg_list:
if response.instances:
all_instances[zone] = response.instances
return all_instances


# [END compute_instances_list_all]


# [START compute_instances_create]
def create_instance(
project: str, zone: str, machine_type: str, machine_name: str, source_image: str
) -> gce.Instance:
"""
Sends an instance creation request to GCP and waits for it to complete.

Args:
project: Name of the project you want to use.
zone: Name of the zone you want to use, for example: us-west3-b
machine_type: Machine type you want to create in following format:
"zones/{zone}/machineTypes/{type_name}". For example:
"zones/europe-west3-c/machineTypes/f1-micro"
machine_name: Name of the new machine.
source_image: Path the the disk image you want to use for your boot
disk. This can be one of the public images
(e.g. "projects/debian-cloud/global/images/family/debian-10")
or a private image you have access to.

Returns:
Instance object.
"""
instance_client = gce.InstancesClient()

# Every machine requires at least one persistent disk
disk = gce.AttachedDisk()
initialize_params = gce.AttachedDiskInitializeParams()
initialize_params.source_image = (
source_image # "projects/debian-cloud/global/images/family/debian-10"
)
initialize_params.disk_size_gb = "10"
disk.initialize_params = initialize_params
disk.auto_delete = True
disk.boot = True
disk.type_ = gce.AttachedDisk.Type.PERSISTENT

# Every machine needs to be connected to a VPC network.
# The 'default' network is created automatically in every project.
network_interface = gce.NetworkInterface()
network_interface.name = "default"

# Collecting all the information into the Instance object
instance = gce.Instance()
instance.name = machine_name
instance.disks = [disk]
instance.machine_type = (
machine_type # "zones/europe-central2-a/machineTypes/n1-standard-8"
)
instance.network_interfaces = [network_interface]

# Preparing the InsertInstanceRequest
request = gce.InsertInstanceRequest()
request.zone = zone # "europe-central2-a"
request.project = project # "diregapic-mestiv"
request.instance_resource = instance

print(f"Creating the {machine_name} instance in {zone}...")
operation = instance_client.insert(request=request)
# wait_result = operation_client.wait(operation=operation.name, zone=zone, project=project)
operation = wait_for_operation(operation, project)
if operation.error:
pass
if operation.warnings:
pass
print(f"Instance {machine_name} created.")
return instance


# [END compute_instances_create]


# [START compute_instances_delete]
def delete_instance(project: str, zone: str, machine_name: str) -> None:
"""
Sends a delete request to GCP and waits for it to complete.

Args:
project: Name of the project you want to use.
zone: Name of the zone you want to use, for example: us-west3-b
machine_name: Name of the machine you want to delete.
"""
instance_client = gce.InstancesClient()

print(f"Deleting {machine_name} from {zone}...")
operation = instance_client.delete(
project=project, zone=zone, instance=machine_name
)
operation = wait_for_operation(operation, project)
if operation.error:
pass
if operation.warnings:
pass
print(f"Instance {machine_name} deleted.")
return


# [END compute_instances_delete]


# [START compute_instances_operation_check]
def wait_for_operation(operation: gce.Operation, project: str) -> gce.Operation:
"""
This method waits for an operation to be completed. Calling this function
will block until the operation is finished.

Args:
operation: The Operation object representing the operation you want to
wait on.
project: Name of the project owning the operation.

Returns:
Finished Operation object.
"""
kwargs = {"project": project, "operation": operation.name}
if operation.zone:
client = gce.ZoneOperationsClient()
# Operation.zone is a full URL address of a zone, so we need to extract just the name
kwargs["zone"] = operation.zone.rsplit("/", maxsplit=1)[1]
elif operation.region:
client = gce.RegionOperationsClient()
# Operation.region is a full URL address of a zone, so we need to extract just the name
kwargs["region"] = operation.region.rsplit("/", maxsplit=1)[1]
else:
client = gce.GlobalOperationsClient()
return client.wait(**kwargs)


# [END compute_instances_operation_check]


def main(project: str, zone: str, machine_name: str) -> None:
# You can find the list of available machine types using:
# https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
machine_type = f"zones/{zone}/machineTypes/f1-micro"
# You can check the list of available public images using:
# gcloud compute images list
source_image = "projects/debian-cloud/global/images/family/debian-10"

create_instance(project, zone, machine_type, machine_name, source_image)

zone_instances = list_instances(project, zone)
print(f"Instances found in {zone}:", ", ".join(i.name for i in zone_instances))

all_instances = list_all_instances(project)
print(f"Instances found in project {project}:")
for i_zone, instances in all_instances.items():
print(f"{i_zone}:", ", ".join(i.name for i in instances))

delete_instance(project, zone, machine_name)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("project_id", help="Google Cloud project ID")
parser.add_argument("zone", help="Google Cloud zone name")
parser.add_argument("machine_name", help="Name for the demo machine")

args = parser.parse_args()

main(args.project_id, args.zone, args.machine_name)
2 changes: 2 additions & 0 deletions samples/snippets/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
google-cloud-compute
pytest
1 change: 1 addition & 0 deletions samples/snippets/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
google-cloud-compute==0.3.0
Loading
0