Como usar as bibliotecas de cliente do Cloud para Python

Neste documento, você verá como usar as bibliotecas de cliente do Cloud para Python no Compute Engine. Veja como autorizar solicitações e como criar, listar e excluir instâncias. Este exercício discute como usar a biblioteca google-api-python-client para acessar os recursos do Compute Engine. Execute este exemplo pela máquina local ou em uma instância de VM, desde que você tenha autorizado a amostra corretamente.

Para ver uma lista completa das bibliotecas de cliente disponíveis, inclusive outras bibliotecas do Google e de código aberto de terceiros, consulte a página "Bibliotecas de cliente".

Para ver o exemplo de código completo com todas as importações necessárias, acesse a página GoogleCloudPlatform/python-docs-samples (em inglês) do GitHub.

Objetivos

  • Definir autorizações do OAuth 2.0 usando a biblioteca oauth2client.
  • Criar uma instância usando a biblioteca google-python-client.
  • Listar instâncias usando a biblioteca google-python-client.
  • Excluir uma instância usando a biblioteca google-python-client.

Custos

Neste tutorial, usamos componentes faturáveis do Google Cloud, incluindo o Compute Engine.

Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

  1. Faça login na sua conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. No Console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar a página do seletor de projetos

  3. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

  4. Instale o SDK do Cloud.
  5. Depois que o SDK estiver instalado, execute gcloud auth application-default login.
  6. Instale a biblioteca google-api-python-client. Normalmente, é possível executar:
    $ pip install --upgrade google-api-python-client

    Para ver mais informações sobre como instalar essa biblioteca, consulte as instruções de instalação. Também é necessário ter o Python 2.7 ou 3.3+ para executar as bibliotecas de cliente do Cloud para Python.

  7. Ative a API Cloud Storage.
  8. Crie um bucket do Cloud Storage e anote o nome do bucket para uso posterior.

Como autorizar solicitações

Neste exemplo, usamos a autorização do OAuth 2.0. Há várias maneiras de autorizar solicitações usando o OAuth 2.0, mas, neste exemplo, usaremos o Application Default Credentials. Isso permite reutilizar as credenciais da ferramenta gcloud se você estiver executando a amostra em uma estação de trabalho local ou reutilizar credenciais de uma conta de serviço se estiver executando a amostra no Compute Engine ou no App Engine. É necessário instalar e autorizar a ferramenta gcloud, conforme as instruções na seção Antes de começar.

As credenciais do Application Default Credentials são fornecidas nas bibliotecas de cliente da API Google automaticamente. Você só precisa compilar e inicializar a API:

compute = googleapiclient.discovery.build('compute', 'v1')

Por exemplo, o seguinte snippet é o método principal desta amostra, que compila e inicializa a API e faz algumas chamadas para criar, listar e excluir uma instância:

def main(project, bucket, zone, instance_name, wait=True):
    compute = googleapiclient.discovery.build('compute', 'v1')

    print('Creating instance.')

    operation = create_instance(compute, project, zone, instance_name, bucket)
    wait_for_operation(compute, project, zone, operation['name'])

    instances = list_instances(compute, project, zone)

    print('Instances in project %s and zone %s:' % (project, zone))
    for instance in instances:
        print(' - ' + instance['name'])

    print("""
Instance created.
It will take a minute or two for the instance to complete work.
Check this URL: http://storage.googleapis.com/{}/output.png
Once the image is uploaded press enter to delete the instance.
""".format(bucket))

    if wait:
        input()

    print('Deleting instance.')

    operation = delete_instance(compute, project, zone, instance_name)
    wait_for_operation(compute, project, zone, operation['name'])

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('project_id', help='Your Google Cloud project ID.')
    parser.add_argument(
        'bucket_name', help='Your Google Cloud Storage bucket name.')
    parser.add_argument(
        '--zone',
        default='us-central1-f',
        help='Compute Engine zone to deploy to.')
    parser.add_argument(
        '--name', default='demo-instance', help='New instance name.')

    args = parser.parse_args()

    main(args.project_id, args.bucket_name, args.zone, args.name)

Como listar instâncias

Com as bibliotecas de cliente do Cloud para Python, é possível listar instâncias através do método compute.instances().list. É necessário fornecer o ID do projeto e a zona em que você quer listar instâncias. Exemplo:

def list_instances(compute, project, zone):
    result = compute.instances().list(project=project, zone=zone).execute()
    return result['items'] if 'items' in result else None

Como adicionar uma instância

Para adicionar uma instância, use o método instances().insert e especifique as propriedades da nova instância. Essas propriedades são especificadas no corpo da solicitação. Para detalhes sobre cada uma delas, consulte a referência da API sobre instances.insert.

Quando você cria uma instância, os valores para as seguintes propriedades precisam ser fornecidos na solicitação:

  • Nome da instância
  • Disco permanente raiz
  • Tipo de máquina
  • Zona
  • Interfaces de rede

Este exemplo inicia uma instância com as seguintes propriedades em uma zona de sua escolha:

  • Tipo de máquina: e2-standard-2
  • Disco permanente raiz: um novo disco permanente baseado na imagem do Debian 8 mais recente
  • A conta de serviço padrão do Compute Engine com os seguintes escopos:

    • https://www.googleapis.com/auth/devstorage.read_write, para que a instância possa ler e gravar arquivos no Cloud Storage
    • https://www.googleapis.com/auth/logging.write, para que os registros de instâncias possam ser enviados para o Cloud Logging
  • Metadados: para especificar comandos que devem ser executados na inicialização da instância.

def create_instance(compute, project, zone, name, bucket):
    # Get the latest Debian Jessie image.
    image_response = compute.images().getFromFamily(
        project='debian-cloud', family='debian-9').execute()
    source_disk_image = image_response['selfLink']

    # Configure the machine
    machine_type = "zones/%s/machineTypes/n1-standard-1" % zone
    startup_script = open(
        os.path.join(
            os.path.dirname(__file__), 'startup-script.sh'), 'r').read()
    image_url = "http://storage.googleapis.com/gce-demo-input/photo.jpg"
    image_caption = "Ready for dessert?"

    config = {
        'name': name,
        'machineType': machine_type,

        # Specify the boot disk and the image to use as a source.
        'disks': [
            {
                'boot': True,
                'autoDelete': True,
                'initializeParams': {
                    'sourceImage': source_disk_image,
                }
            }
        ],

        # Specify a network interface with NAT to access the public
        # internet.
        'networkInterfaces': [{
            'network': 'global/networks/default',
            'accessConfigs': [
                {'type': 'ONE_TO_ONE_NAT', 'name': 'External NAT'}
            ]
        }],

        # Allow the instance to access cloud storage and logging.
        'serviceAccounts': [{
            'email': 'default',
            'scopes': [
                'https://www.googleapis.com/auth/devstorage.read_write',
                'https://www.googleapis.com/auth/logging.write'
            ]
        }],

        # Metadata is readable from the instance and allows you to
        # pass configuration from deployment scripts to instances.
        'metadata': {
            'items': [{
                # Startup script is automatically executed by the
                # instance upon startup.
                'key': 'startup-script',
                'value': startup_script
            }, {
                'key': 'url',
                'value': image_url
            }, {
                'key': 'text',
                'value': image_caption
            }, {
                'key': 'bucket',
                'value': bucket
            }]
        }
    }

    return compute.instances().insert(
        project=project,
        zone=zone,
        body=config).execute()

As seções a seguir descrevem os parâmetros de criação de instâncias.

Discos permanentes raiz

Todas as instâncias precisam ser inicializadas a partir de um disco permanente raiz. Esse disco contém todos os arquivos necessários para iniciar uma instância. Ao criar um disco permanente raiz, você precisa selecionar uma imagem pública ou uma imagem personalizada para aplicar ao disco. No exemplo acima, foi criado um novo disco permanente raiz com base no Debian 8 junto com a instância. Entretanto, também crie um disco com antecedência e anexe-o à instância.

Metadados de instância

Ao criar sua instância, talvez você queira incluir metadados de instância, como um script de inicialização, variáveis de configuração e chaves SSH. No exemplo acima, você usou o campo metadata no corpo da solicitação para especificar um script de inicialização para a instância, além de algumas variáveis de configuração como pares de chave-valor. O script de inicialização, listado abaixo, mostra como ler essas variáveis e usá-las para aplicar texto a uma imagem e fazer o upload no Cloud Storage.

apt-get update
apt-get -y install imagemagick

# Use the metadata server to get the configuration specified during
# instance creation. Read more about metadata here:
# https://cloud.google.com/compute/docs/metadata#querying
IMAGE_URL=$(curl http://metadata/computeMetadata/v1/instance/attributes/url -H "Metadata-Flavor: Google")
TEXT=$(curl http://metadata/computeMetadata/v1/instance/attributes/text -H "Metadata-Flavor: Google")
CS_BUCKET=$(curl http://metadata/computeMetadata/v1/instance/attributes/bucket -H "Metadata-Flavor: Google")

mkdir image-output
cd image-output
wget $IMAGE_URL
convert * -pointsize 30 -fill white -stroke black -gravity center -annotate +10+40 "$TEXT" output.png

# Create a Google Cloud Storage bucket.
gsutil mb gs://$CS_BUCKET

# Store the image in the Google Cloud Storage bucket and allow all users
# to read it.
gsutil cp -a public-read output.png gs://$CS_BUCKET/output.png

Excluir uma instância

Para excluir uma instância, chame o método instances().delete e forneça o nome, a zona e o ID do projeto da instância a ser excluída. Como você definiu o parâmetro autoDelete para o disco de inicialização, ele também é excluído com a instância. Essa configuração está desativada por padrão, porém, é útil quando seu caso de uso faz chamadas para excluir discos e instâncias simultaneamente.

def delete_instance(compute, project, zone, name):
    return compute.instances().delete(
        project=project,
        zone=zone,
        instance=name).execute()

Executar o exemplo

Execute a amostra completa fazendo o download do código e executando-o na linha de comando. Certifique-se de fazer o download do arquivo create_instance.py e do arquivo startup-script.sh. Para executar a amostra:

python create_instance.py --name [INSTANCE_NAME] --zone [ZONE] [PROJECT_ID] [CLOUD_STORAGE_BUCKET]

em que:

  • [INSTANCE_NAME] é o nome da instância a ser criada;
  • [ZONE] é a zona pretendida para esta solicitação.
  • [PROJECT_ID] é o ID do nosso projeto.
  • [CLOUD_STORAGE_BUCKET] é o nome do bucket configurado inicialmente, mas sem o prefixo gs://.

Exemplo:

python python-example.py --name example-instance --zone us-central1-a example-project my-gcs-bucket

Aguardar a conclusão de operações

As solicitações feitas à API Compute Engine que modificam recursos, como instâncias, retornam uma resposta confirmando a solicitação. Essa confirmação viabiliza a verificação do status da operação solicitada. Como as operações podem levar alguns minutos para serem concluídas, geralmente é mais fácil esperar a operação ser concluída antes de continuar. Este método auxiliar aguarda até que a operação seja concluída antes de retornar:

def wait_for_operation(compute, project, zone, operation):
    print('Waiting for operation to finish...')
    while True:
        result = compute.zoneOperations().get(
            project=project,
            zone=zone,
            operation=operation).execute()

        if result['status'] == 'DONE':
            print("done.")
            if 'error' in result:
                raise Exception(result['error'])
            return result

        time.sleep(1)

Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Excluir o bucket do Cloud Storage

Para excluir um bucket do Cloud Storage:

  1. No Console do Cloud, acesse a página Navegador do Cloud Storage.

    Acessar a página "Navegador do Cloud Storage"

  2. Clique na caixa de seleção do bucket que você quer excluir.
  3. Para excluir o bucket, clique em Excluir .

A seguir

  • Faça o download e veja a amostra de código completa. A amostra completa contém um pequeno exemplo de como usar todos esses métodos juntos. Sinta-se à vontade para fazer o download desse exemplo, alterá-lo e executá-lo para atender às suas necessidades.
  • Leia a referência da API para aprender a executar outras tarefas com ela.