Can I replicate `create-with-container` gcloud sdk command using the googleapiclient python client

525 Views Asked by At

I currently have a docker container on the gcloud container repository which I want to launch an instance of in order to run a calculation, save a result and close:

gcloud compute instances create-with-container test-1 \
--machine-type=n1-standard-4 \
--boot-disk-size=20GB \
--container-image=eu.gcr.io/<container-link> \
--container-env=GCLOUD_INPUT_FILENAME=file.txt \
--container-env=GCLOUD_PROJECT=project-name

However, I want to be able to launch these instances using a web-interface (flask) which implies I want to use the googleapiclient (python) in order to create and manage these instances:

It looks like while you can create a instance creation order using the discovery api:

compute = googleclientapi.discovery.build('compute', 'v1')
compute.instances().insert(...).execute()

but it doesn't look like it is possible to emulate create-with-container gcloud sdk command, although you can pass 'machineImage' as part of the creation request.

Can one create a compute instance 'with-container' without using subprocess to call the gcloud sdk

OR

Can I convert my create-with-container instance into a machine image and then use the googleapi client?

2

There are 2 best solutions below

0
Indrajeet Gour On

Just for FYI, what I found from the log-http logging(I know it is not the right answer)

==== request start ====
uri: https://compute.googleapis.com/batch/compute/v1
method: POST
== headers start ==
b'authorization': --- Token Redacted ---
b'content-length': b'479'
b'content-type': b'multipart/mixed; boundary="===============34234234234234=="'
b'user-agent': b'google-cloud-sdk gcloud/329.0.0 command/gcloud.compute.instances.create-with-container invocation-id/0dd6a37ac0624ac4b00e30a44da environment/devshell environment-version/None interactive/False from-script/False python/3.7.3 term/screen (Linux 5.4.89+)'
== headers end ==

"create-with-container" is passed through the header, I did not find the body for the same.

0
DazWilkin On

The code would benefit from refinement but here's a solution:

import os

from google.cloud import compute_v1
from google.cloud.compute_v1 import types


project=os.getenv("PROJECT")
number=os.getenv("NUMBER")
zone=os.getenv("ZONE")

machine_type=os.getenv("TYPE")

name=os.getenv("NAME")

# Compute Engine default
email=f"{number}[email protected]"

# Define a non-trivial container with command and args
value="""
spec:
  containers:
  - name: foo
    image: gcr.io/google-containers/busybox@sha256:d8d3bc2c183ed2f9f10e7258f84971202325ee6011ba137112e01e30f206de67
    command:
    - /bin/sh
    args:
    - -c
    - |
      while true
      do
        echo "Hello"
        sleep 15
      done
    stdin: true
    tty: true
    restartPolicy: Always
"""

client = compute_v1.InstancesClient()

request = types.InsertInstanceRequest(
    project=project,
    zone=zone,
    instance_resource=types.Instance(
        name=name,
        machine_type=f"zones/{zone}/machineTypes/{machine_type}",
        disks=[
            types.AttachedDisk(
                device_name="foo",
                boot=True,
                auto_delete=True,
                initialize_params=types.AttachedDiskInitializeParams(
                    disk_size_gb=10,
                    disk_type=f"zones/{zone}/diskTypes/pd-balanced",
                    source_image="projects/cos-cloud/global/images/cos-stable-101-17162-40-13",
                ),
            ),
        ],
        network_interfaces=[
            types.NetworkInterface(
                access_configs=[
                    types.AccessConfig(
                        name="External NAT",
                        network_tier="STANDARD",
                    ),
                ],
            ),
        ],
        metadata=types.Metadata(
            items=[{
                "key":"gce-container-declaration",
                "value": value,
            }],
        ),
        service_accounts=[
            types.ServiceAccount(
                email=email,
                scopes=[
                    "https://www.googleapis.com/auth/devstorage.read_only",
                    "https://www.googleapis.com/auth/logging.write",
                    "https://www.googleapis.com/auth/monitoring.write",
                    "https://www.googleapis.com/auth/servicecontrol",
                    "https://www.googleapis.com/auth/service.management.readonly",
                    "https://www.googleapis.com/auth/trace.append"
                ],
            ),
        ],
    ),
)

response=client.insert(
    request=request,
)