Exemplo: use as bibliotecas do Azure para criar um banco de dados

Este exemplo demonstra como usar as bibliotecas de gerenciamento do SDK do Azure em um script Python para criar uma instância de servidor flexível e um banco de dados do Banco de Dados do Azure para MySQL. Ele também fornece um script simples para consultar o banco de dados usando a biblioteca do mysql-conector (não é parte do SDK do Azure). Você pode usar um código semelhante para criar uma instância de servidor flexível e um banco de dados do Banco de Dados do Azure para PostgreSQL.

Comandos equivalentes da CLI do Azure serão abordados depois neste artigo. Se preferir usar o portal do Azure, confira Criar um servidor MySQL ou Criar um servidor PostgreSQL.)

Todos os comandos neste artigo funcionam da mesma forma no bash do Linux/macOS e nos shells de comando do Windows, a menos que haja uma observação.

1: configurar seu ambiente de desenvolvimento

Caso ainda não tenha feito isso, configure um ambiente onde você possa executar o código. Estas são algumas opções:

2: instalar os pacotes de biblioteca do Azure necessários

Crie um arquivo chamado requirements.txt com o conteúdo abaixo:

azure-mgmt-resource
azure-mgmt-rdbms
azure-identity
mysql-connector-python

Em um terminal com o ambiente virtual ativado, instale os requisitos:

pip install -r requirements.txt

Observação

No Windows, a tentativa de instalar a biblioteca do MySQL em uma biblioteca Python de 32 bits produz um erro sobre o arquivo mysql.h. Nesse caso, instale uma versão de 64 bits do Python e tente novamente.

3: Escrever o código para criar o banco de dados

Crie um arquivo Python com o nome provision_db.py com o código a seguir. Os comentários explicam os detalhes. Em particular, especifique variáveis de ambiente para AZURE_SUBSCRIPTION_ID e PUBLIC_IP_ADDRESS. A última variável é o endereço IP da estação de trabalho para que este exemplo seja executado. Você pode usar WhatsIsMyIP para encontrar seu endereço IP.

import random, os
from azure.identity import DefaultAzureCredential
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.rdbms.mysql_flexibleservers import MySQLManagementClient
from azure.mgmt.rdbms.mysql_flexibleservers.models import Server, ServerVersion

# Acquire a credential object using CLI-based authentication.
credential = DefaultAzureCredential()

# Retrieve subscription ID from environment variable
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]

# Constants we need in multiple places: the resource group name and the region
# in which we provision resources. You can change these values however you want.
RESOURCE_GROUP_NAME = 'PythonAzureExample-DB-rg'
LOCATION = "southcentralus"

# Step 1: Provision the resource group.
resource_client = ResourceManagementClient(credential, subscription_id)

rg_result = resource_client.resource_groups.create_or_update(RESOURCE_GROUP_NAME,
    { "location": LOCATION })

print(f"Provisioned resource group {rg_result.name}")

# For details on the previous code, see Example: Provision a resource group
# at https://docs.microsoft.com/azure/developer/python/azure-sdk-example-resource-group


# Step 2: Provision the database server

# We use a random number to create a reasonably unique database server name.
# If you've already provisioned a database and need to re-run the script, set
# the DB_SERVER_NAME environment variable to that name instead.
#
# Also set DB_USER_NAME and DB_USER_PASSWORD variables to avoid using the defaults.

db_server_name = os.environ.get("DB_SERVER_NAME", f"python-azure-example-mysql-{random.randint(1,100000):05}")
db_admin_name = os.environ.get("DB_ADMIN_NAME", "azureuser")
db_admin_password = os.environ.get("DB_ADMIN_PASSWORD", "ChangePa$$w0rd24")

# Obtain the management client object
mysql_client = MySQLManagementClient(credential, subscription_id)

# Provision the server and wait for the result
poller = mysql_client.servers.begin_create(RESOURCE_GROUP_NAME,
    db_server_name, 
    Server(
        location=LOCATION,
        administrator_login=db_admin_name,
        administrator_login_password=db_admin_password,
        version=ServerVersion.FIVE7
    )
)

server = poller.result()

print(f"Provisioned MySQL server {server.name}")

# Step 3: Provision a firewall rule to allow the local workstation to connect

RULE_NAME = "allow_ip"
ip_address = os.environ["PUBLIC_IP_ADDRESS"]

# For the above code, create an environment variable named PUBLIC_IP_ADDRESS that
# contains your workstation's public IP address as reported by a site like
# https://whatismyipaddress.com/.

# Provision the rule and wait for completion
poller = mysql_client.firewall_rules.begin_create_or_update(RESOURCE_GROUP_NAME,
    db_server_name, RULE_NAME, 
    { "start_ip_address": ip_address, "end_ip_address": ip_address }  
)

firewall_rule = poller.result()

print(f"Provisioned firewall rule {firewall_rule.name}")


# Step 4: Provision a database on the server

db_name = os.environ.get("DB_NAME", "example-db1")
 
poller = mysql_client.databases.begin_create_or_update(RESOURCE_GROUP_NAME,
    db_server_name, db_name, {})

db_result = poller.result()

print(f"Provisioned MySQL database {db_result.name} with ID {db_result.id}")

Autenticação no código

Mais adiante neste artigo, você entra no Azure com a CLI do Azure para executar o código de exemplo. Se sua conta tiver permissões para criar grupos de recursos e recursos de armazenamento em sua assinatura do Azure, o código será executado com êxito.

Para usar esse código em um script de produção, você pode definir variáveis de ambiente para usar um método baseado em entidade de serviço para autenticação. Para saber mais, confira Como autenticar aplicativos Python com serviços do Azure. Você precisa garantir que a entidade de serviço tenha permissões suficientes para criar grupos de recursos e recursos de armazenamento em sua assinatura, atribuindo uma função apropriada no Azure; por exemplo, a função Colaborador na sua assinatura.

Para o servidor de banco de dados PostreSQL, consulte:

4: executar o script

  1. Caso ainda não tenha feito isso, entre no Azure usando a CLI do Azure:

    az login
    
  2. Defina as variáveis de ambiente AZURE_SUBSCRIPTION_ID e PUBLIC_IP_ADDRESS. Você pode executar o comando az account show para obter sua ID de assinatura da propriedade id na saída. Você pode usar WhatsIsMyIP para encontrar seu endereço IP.

    set AZURE_SUBSCRIPTION_ID=00000000-0000-0000-0000-000000000000
    set PUBLIC_IP_ADDRESS=<Your public IP address>
    
  3. Opcionalmente, defina as variáveis de ambiente DB_SERVER_NAME , DB_ADMIN_NAME e DB_ADMIN_PASSWORD, caso contrário, os padrões de código serão usados.

  4. Executar o script:

    python provision_db.py
    

5: Inserir um registro e consultar o banco de dados

Crie um arquivo chamado use_db.py com o código a seguir. Observe as dependências nas variáveis de ambiente DB_SERVER_NAME, DB_ADMIN_NAME e DB_ADMIN_PASSWORD. Você obtém esses valores da saída da execução do código anterior provision_db.py ou no próprio código.

Esse código só funciona para MySQL; você deve usar bibliotecas diferentes para PostgreSQL.

import os
import mysql.connector

db_server_name = os.environ["DB_SERVER_NAME"]
db_admin_name = os.getenv("DB_ADMIN_NAME", "azureuser")
db_admin_password = os.getenv("DB_ADMIN_PASSWORD", "ChangePa$$w0rd24")

db_name = os.getenv("DB_NAME", "example-db1")
db_port = os.getenv("DB_PORT", 3306)

connection = mysql.connector.connect(user=db_admin_name,
    password=db_admin_password, host=f"{db_server_name}.mysql.database.azure.com",
    port=db_port, database=db_name, ssl_ca='./BaltimoreCyberTrustRoot.crt.pem')

cursor = connection.cursor()

"""
# Alternate pyodbc connection; include pyodbc in requirements.txt
import pyodbc

driver = "{MySQL ODBC 5.3 UNICODE Driver}"

connect_string = f"DRIVER={driver};PORT=3306;SERVER={db_server_name}.mysql.database.azure.com;" \
                 f"DATABASE={DB_NAME};UID={db_admin_name};PWD={db_admin_password}"

connection = pyodbc.connect(connect_string)
"""

table_name = "ExampleTable1"

sql_create = f"CREATE TABLE {table_name} (name varchar(255), code int)"

cursor.execute(sql_create)
print(f"Successfully created table {table_name}")

sql_insert = f"INSERT INTO {table_name} (name, code) VALUES ('Azure', 1)"
insert_data = "('Azure', 1)"

cursor.execute(sql_insert)
print("Successfully inserted data into table")

sql_select_values= f"SELECT * FROM {table_name}"

cursor.execute(sql_select_values)
row = cursor.fetchone()

while row:
    print(str(row[0]) + " " + str(row[1]))
    row = cursor.fetchone()

connection.commit()

Todo esse código usa o API mysql.connector. A única parte específica do Azure é o domínio de host completo para servidor MySQL (mysql.database.azure.com).

Em seguida, baixe o certificado necessário para comunicação via TSL/SSL com o servidor do Banco de Dados do Azure para MySQL em https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem e salve o arquivo de certificado na mesma pasta do arquivo Python. Para obter mais informações, consulte Obter um certificado SSL na documentação do Banco de Dados do Azure para MySQL.

Finalmente, execute o código:

python use_db.py

Se você vir um erro informando que o endereço IP do cliente não é permitido, verifique se você definiu a variável de ambiente PUBLIC_IP_ADDRESS corretamente. Se você já tiver criado o servidor MySQL com o endereço IP errado, poderá adicionar outro no portal do Azure. No portal, selecione o servidor MySQL e então selecione Segurança de conexão. Adicione o endereço IP da sua estação de trabalho à lista de endereços IP permitidos.

6: limpar recursos

Execute o comando az group delete se você não precisar manter o grupo de recursos e os recursos de armazenamento criados neste exemplo.

Os grupos de recursos não incorrem em encargos adicionais em sua assinatura, mas recursos, como contas de armazenamento, no grupo de recursos podem continuar a incorrer em encargos. É prática recomendada limpar qualquer grupo que você não esteja usando ativamente. O argumento --no-wait permite que o comando seja retornado imediatamente, em vez de esperar a conclusão da operação.

az group delete -n PythonAzureExample-DB-rg  --no-wait

Você também pode usar o método ResourceManagementClient.resource_groups.begin_delete para excluir um grupo de recursos do código. O código em Exemplo: criar um grupo de recursos demonstra o uso.

Para referência: comandos equivalentes da CLI do Azure

Os seguintes comandos da CLI do Azure CLI completam as mesmos etapas de provisionamento que o script Python. Para um banco de dados PostgreSQL, use comandos do az postgres flexible-server.

az group create --location southcentralus --name PythonAzureExample-DB-rg

az mysql flexible-server create --location southcentralus --resource-group PythonAzureExample-DB-rg ^
    --name python-azure-example-mysql-12345 --admin-user azureuser --admin-password ChangePa$$w0rd24 ^
    --sku-name Standard_B1ms --version 5.7 --yes

# Change the IP address to the public IP address of your workstation, that is, the address shown
# by a site like https://whatismyipaddress.com/.

az mysql flexible-server firewall-rule create --resource-group PythonAzureExample-DB-rg --name python-azure-example-mysql-12345 ^
    --rule-name allow_ip --start-ip-address 10.11.12.13 --end-ip-address 10.11.12.13

az mysql flexible-server db create --resource-group PythonAzureExample-DB-rg --server-name python-azure-example-mysql-12345 ^
    --database-name example-db1

Confira também