Plug-in da biblioteca de cliente boto

Neste tutorial, você aprenderá como escrever um programa simples em Python que realiza operações básicas do Cloud Storage usando a API XML. Para seguir este documento, é necessário estar familiarizado com o Python e com os conceitos e operações do Cloud Storage apresentados no guia de início rápido do Console.

É melhor usar as bibliotecas de cliente do Cloud Storage?

Normalmente, o ideal é usar a biblioteca de cliente do Cloud Storage para que aplicativos em Python funcionem com buckets e objetos do Cloud Storage. As bibliotecas de cliente do Cloud Storage oferecem mais flexibilidade. Além disso, elas são utilizadas nas amostras de código nos guias do Cloud Storage. Use este guia se você quiser interagir especificamente com o Cloud Storage usando a API XML e a biblioteca boto.

Como configurar o ambiente

Antes de iniciar este tutorial, conclua estas etapas:

  1. Instale uma versão independente da gsutil no seu computador.

  2. Instale a biblioteca boto e o gcs-oauth2-boto-plugin.

    Boto é uma biblioteca Python (em inglês) de código aberto que é usada como uma interface do Cloud Storage. O gcs-oauth2-boto-plugin (em inglês) é um plug-in de autenticação para o framework boto. Ele fornece credenciais do OAuth 2.0 que podem ser usadas com o Cloud Storage.

    A configuração para usar a biblioteca boto e o plug-in oauth2 depende do seu sistema. Oriente-se pelos exemplos de configuração abaixo. São comandos que instalam o pip (em inglês) e o usam para instalar outros pacotes. Os três últimos comandos mostram como testar a importação dos dois módulos para verificar a instalação.

    Debian e Ubuntu

    wget https://bootstrap.pypa.io/get-pip.py
    sudo python get-pip.py
    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get install gcc python-dev python-setuptools libffi-dev libssl-dev
    sudo pip install virtualenv
    virtualenv venv
    source ./venv/bin/activate
    (venv)pip install gcs-oauth2-boto-plugin
    (venv)python
    >>>import boto
    >>>import gcs_oauth2_boto_plugin

    CentOS, RHEL e Fedora

    wget https://bootstrap.pypa.io/get-pip.py
    sudo python get-pip.py
    sudo yum install gcc openssl-devel python-devel python-setuptools libffi-devel
    sudo pip install virtualenv
    virtualenv venv
    source ./venv/bin/activate
    (venv)pip install gcs-oauth2-boto-plugin
    (venv)python
    >>>import boto
    >>>import gcs_oauth2_boto_plugin
  3. Configure o arquivo de configuração boto para usar o OAuth2.0.

    É possível configurar o arquivo de configuração do boto para usar a conta de serviço ou as credenciais da conta de usuário. As credenciais da conta de serviço são o tipo preferencial para autenticar em nome de um serviço ou aplicativo. As credenciais da conta de usuário são o tipo preferencial para autenticar solicitações em nome de um usuário específico (ou seja, um humano). Para mais informações sobre esses dois tipos de credenciais, consulte os tipos de credenciais aceitos.

    Contas de serviço

    Para usar as credenciais da conta de serviço, siga estas etapas:

    1. Use uma conta de serviço atual ou crie uma nova e faça o download da chave privada associada. O download da chave como um arquivo .json é o padrão e preferível, mas o formato .p12 também é aceito.

    2. Configure o arquivo .boto com a conta de serviço. É possível fazer isso com a gsutil.

      gsutil config -e

      O comando solicita que você informe o endereço de e-mail e o local da chave privada da conta de serviço (.json ou .p12). Certifique-se de ter a chave privada no computador em que você está executando o comando gsutil.

    Contas de usuário

    Para usar as credenciais de conta de usuário, siga estas etapas:

    1. Crie um arquivo .boto, se ainda não tiver um. É possível fazer isso com a gsutil.

      gsutil config
    2. Use um ID do cliente atual de um aplicativo ou crie um ID novo.

    3. Edite o arquivo .boto. Na seção [OAuth2], especifique os valores client_id e client_secret com aqueles que você gerou.

    4. Execute o comando gsutil config novamente para gerar um token de atualização com base no ID do cliente e na chave secreta inserida.

      Se você receber uma mensagem de erro que indique que não é possível fazer backup do .boto, remova ou renomeie o arquivo de configuração de backup .boto.bak.

    5. Configure a lógica de fallback do token de atualização.

      O gcs-oauth2-boto-plugin requer uma lógica de fallback para gerar tokens de autorização quando você usa credenciais de aplicativo. No entanto, ela não é necessária ao usar uma conta de serviço.

      Você tem as opções a seguir para ativar o fallback:

      • Defina client_id e client_secret no arquivo de configuração .boto. Essa é a opção recomendada e necessária para usar a gsutil com seu novo arquivo de configuração .boto.

      • Defina as variáveis de ambiente OAUTH2_CLIENT_ID e OAUTH2_CLIENT_SECRET.

      • Use a função SetFallbackClientIdAndSecret, como demonstrado nos exemplos abaixo.

Como trabalhar com o Cloud Storage

Como configurar o arquivo de origem em Python

Para iniciar este tutorial, use o editor de texto da sua preferência para criar um novo arquivo em Python. Depois, adicione as diretivas, instruções de importação, configurações e atribuições de constantes abaixo.

Observe que o código a seguir usa a função SetFallbackClientIdAndSecret como fallback para gerar tokens de atualização. Consulte Como configurar o ambiente para ver outras maneiras de especificar um fallback. Se você estiver usando uma conta de serviço para fazer a autenticação, não será necessário incluir a lógica de fallback.

#!/usr/bin/python

import boto
import gcs_oauth2_boto_plugin
import os
import shutil
import StringIO
import tempfile
import time

# URI scheme for Cloud Storage.
GOOGLE_STORAGE = 'gs'
# URI scheme for accessing local files.
LOCAL_FILE = 'file'

# Fallback logic. In https://console.cloud.google.com/
# under Credentials, create a new client ID for an installed application.
# Required only if you have not configured client ID/secret in
# the .boto file or as environment variables.
CLIENT_ID = 'your client id'
CLIENT_SECRET = 'your client secret'
gcs_oauth2_boto_plugin.SetFallbackClientIdAndSecret(CLIENT_ID, CLIENT_SECRET)

Como criar buckets

O código a seguir cria dois buckets. É necessário que nomes dos buckets sejam globalmente únicos (consulte as diretrizes de nomenclatura). Portanto, um carimbo de data/hora é anexado a cada nome de bucket para garantir que não exista outro igual.

Se esses nomes de bucket já estiverem em uso, será necessário modificar o código para gerar nomes únicos.

now = time.time()
CATS_BUCKET = 'cats-%d' % now
DOGS_BUCKET = 'dogs-%d' % now

# Your project ID can be found at https://console.cloud.google.com/
# If there is no domain for your project, then project_id = 'YOUR_PROJECT'
project_id = 'YOUR_DOMAIN:YOUR_PROJECT'

for name in (CATS_BUCKET, DOGS_BUCKET):
  # Instantiate a BucketStorageUri object.
  uri = boto.storage_uri(name, GOOGLE_STORAGE)
  # Try to create the bucket.
  try:
    # If the default project is defined,
    # you do not need the headers.
    # Just call: uri.create_bucket()
    header_values = {"x-goog-project-id": project_id}
    uri.create_bucket(headers=header_values)

    print 'Successfully created bucket "%s"' % name
  except boto.exception.StorageCreateError, e:
    print 'Failed to create bucket:', e

Como listar buckets

Para recuperar uma lista de todos os buckets, faça uma chamada storage_uri() para instanciar um objeto BucketStorageUri, especificando a string vazia como o URI. Depois, chame o método de instância get_all_buckets().

uri = boto.storage_uri('', GOOGLE_STORAGE)
# If the default project is defined, call get_all_buckets() without arguments.
for bucket in uri.get_all_buckets(headers=header_values):
  print bucket.name

Como fazer upload de objetos

Para fazer upload de objetos, crie um objeto de arquivo (aberto para leitura) que direcione para seu arquivo local, bem como um objeto de URI de armazenamento que direcione para o objeto de destino no Cloud Storage. Chame o método de instância set_contents_from_file(), especificando o identificador do arquivo como o argumento.

# Make some temporary files.
temp_dir = tempfile.mkdtemp(prefix='googlestorage')
tempfiles = {
    'labrador.txt': 'Who wants to play fetch? Me!',
    'collie.txt': 'Timmy fell down the well!'}
for filename, contents in tempfiles.iteritems():
  with open(os.path.join(temp_dir, filename), 'w') as fh:
    fh.write(contents)

# Upload these files to DOGS_BUCKET.
for filename in tempfiles:
  with open(os.path.join(temp_dir, filename), 'r') as localfile:

    dst_uri = boto.storage_uri(
        DOGS_BUCKET + '/' + filename, GOOGLE_STORAGE)
    # The key-related functions are a consequence of boto's
    # interoperability with Amazon S3 (which employs the
    # concept of a key mapping to localfile).
    dst_uri.new_key().set_contents_from_file(localfile)
  print 'Successfully created "%s/%s"' % (
      dst_uri.bucket_name, dst_uri.object_name)

shutil.rmtree(temp_dir)  # Don't forget to clean up!

Como listar objetos

Para listar todos os objetos em um bucket, faça uma chamada storage_uri() e especifique o URI do bucket e o esquema do URI do Cloud Storage como os argumentos. Depois, recupere uma lista de objetos usando o método de instância get_bucket().

uri = boto.storage_uri(DOGS_BUCKET, GOOGLE_STORAGE)
for obj in uri.get_bucket():
  print '%s://%s/%s' % (uri.scheme, uri.bucket_name, obj.name)
  print '  "%s"' % obj.get_contents_as_string()

Como fazer o download de objetos e copiá-los

O código a seguir faz leituras de objetos em DOGS_BUCKET e os copia para seu diretório base e para CATS_BUCKET. Ele também mostra que é possível usar a biblioteca boto para operar em arquivos locais e objetos do Cloud Storage na mesma interface.

dest_dir = os.getenv('HOME')
for filename in ('collie.txt', 'labrador.txt'):
  src_uri = boto.storage_uri(
      DOGS_BUCKET + '/' + filename, GOOGLE_STORAGE)

  # Create a file-like object for holding the object contents.
  object_contents = StringIO.StringIO()

  # The unintuitively-named get_file() doesn't return the object
  # contents; instead, it actually writes the contents to
  # object_contents.
  src_uri.get_key().get_file(object_contents)

  local_dst_uri = boto.storage_uri(
      os.path.join(dest_dir, filename), LOCAL_FILE)

  bucket_dst_uri = boto.storage_uri(
      CATS_BUCKET + '/' + filename, GOOGLE_STORAGE)

  for dst_uri in (local_dst_uri, bucket_dst_uri):
    object_contents.seek(0)
    dst_uri.new_key().set_contents_from_file(object_contents)

  object_contents.close()

Como fazer transferências por streaming

Para fazer um upload por streaming, use o código a seguir:

dst_uri = boto.storage_uri(<bucket> + '/' + <object>, 'gs')
dst_uri.new_key().set_contents_from_stream(<stream object>)

Por exemplo, o código a seguir faz um upload por streaming de um arquivo chamado data_file para um objeto com o mesmo nome:

filename = 'data_file'
MY_BUCKET = 'my_app_bucket'
my_stream = open(filename, 'rb')
dst_uri = boto.storage_uri(MY_BUCKET + '/' + filename, 'gs')
dst_uri.new_key().set_contents_from_stream(my_stream)

Para fazer um download por streaming, use o código a seguir:

import sys

src_uri = boto.storage_uri(<bucket> + '/' + <object>, 'gs')
src_uri.get_key().get_file(sys.stdout)

Por exemplo, o código a seguir faz um download por streaming de um objeto chamado data_file:

downloaded_file = 'saved_data_file'
MY_BUCKET = 'my_app_bucket'
object_name = 'data_file'
src_uri = boto.storage_uri(MY_BUCKET + '/' + object_name, 'gs')
src_uri.get_key().get_file(sys.stdout)

Como alterar ACLs de objeto

Com o código a seguir, é possível conceder as permissões FULL_CONTROL específicas da conta do Google ao labrador.txt. Lembre-se de substituir valid-email-address por um endereço de e-mail válido de uma Conta do Google.

uri = boto.storage_uri(DOGS_BUCKET + '/labrador.txt', GOOGLE_STORAGE)
print str(uri.get_acl())
uri.add_email_grant('FULL_CONTROL', 'valid-email-address')
print str(uri.get_acl())

Como ler metadados de buckets e objetos

O código a seguir recupera e imprime os metadados associados a um bucket e a um objeto.

# Print ACL entries for DOGS_BUCKET.
bucket_uri = boto.storage_uri(DOGS_BUCKET, GOOGLE_STORAGE)
for entry in bucket_uri.get_bucket().get_acl().entries.entry_list:
  entry_id = entry.scope.id
  if not entry_id:
    entry_id = entry.scope.email_address
  print 'SCOPE: %s' % entry_id
  print 'PERMISSION: %s\n' % entry.permission

# Print object metadata and ACL entries.
object_uri = boto.storage_uri(DOGS_BUCKET + '/labrador.txt', GOOGLE_STORAGE)
key = object_uri.get_key()
print ' Object size:\t%s' % key.size
print ' Last mod:\t%s' % key.last_modified
print ' MIME type:\t%s' % key.content_type
print ' MD5:\t%s' % key.etag.strip('"\'') # Remove surrounding quotes
for entry in key.get_acl().entries.entry_list:
  entry_id = entry.scope.id
  if not entry_id:
    entry_id = entry.scope.email_address
  print 'SCOPE: %s' % entry_id
  print 'PERMISSION: %s\n' % entry.permission

Como excluir objetos e buckets

Para concluir este tutorial, o código a seguir exclui os objetos e buckets criados por você. É necessário que o bucket esteja vazio para ser excluído. Portanto, exclua primeiro os objetos.

for bucket in (CATS_BUCKET, DOGS_BUCKET):
  uri = boto.storage_uri(bucket, GOOGLE_STORAGE)
  for obj in uri.get_bucket():
    print 'Deleting object: %s...' % obj.name
    obj.delete()
  print 'Deleting bucket: %s...' % uri.bucket_name
  uri.delete_bucket()