

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Execução de consultas SQL no Amazon Redshift usando o Terraform
<a name="execute-redshift-sql-queries-using-terraform"></a>

*Sylvia Qi e Aditya Ambati, Amazon Web Services*

## Resumo
<a name="execute-redshift-sql-queries-using-terraform-summary"></a>

Usar a infraestrutura como código (IaC) para a implantação e o gerenciamento do Amazon Redshift é uma prática predominante na empresa. DevOps A IaC facilita a implantação e a configuração de diversos recursos do Amazon Redshift, como clusters, snapshots e grupos de parâmetros. No entanto, a IaC não abrange o gerenciamento de recursos de banco de dados, como tabelas, esquemas, visualizações e procedimentos armazenados. Esses elementos de banco de dados são gerenciados por meio de consultas SQL e não são diretamente compatíveis com as ferramentas de IaC. Embora existam soluções e ferramentas para gerenciar esses recursos, você pode preferir não adicionar ferramentas extras à sua pilha tecnológica.

Este padrão descreve uma metodologia que usa o Terraform para implantar recursos de banco de dados do Amazon Redshift, incluindo tabelas, esquemas, visualizações e procedimentos armazenados. O padrão faz a distinção entre dois tipos de consultas SQL:
+ **Consultas não repetíveis**: essas consultas são executadas uma única vez durante a implantação inicial do Amazon Redshift para estabelecer os componentes essenciais do banco de dados. 
+ **Consultas repetíveis**: essas consultas são imutáveis e podem ser executadas novamente sem impactar o banco de dados. A solução emprega o Terraform para monitorar mudanças nas consultas repetíveis e aplicá-las de forma apropriada.

Para obter mais detalhes, consulte *Explicação passo a passo da solução* em [Informações adicionais](#execute-redshift-sql-queries-using-terraform-additional).

## Pré-requisitos e limitações
<a name="execute-redshift-sql-queries-using-terraform-prereqs"></a>

**Pré-requisitos **

Você deve ter um ativo Conta da AWS e instalar o seguinte em sua máquina de implantação:
+ [AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) (AWS CLI)
+ Um [AWS CLI perfil](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) configurado com permissões do Amazon Redshift read/write 
+ [Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) versão 1.6.2 ou versões posteriores
+ [Python 3](https://www.python.org/downloads/)
+ [Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)

**Limitações**
+ Esta solução fornece suporte para um único banco de dados do Amazon Redshift, pois o Terraform permite a criação de apenas um banco de dados durante a criação do cluster.
+ Este padrão não inclui testes para validar as alterações nas consultas repetíveis antes de aplicá-las. Recomendamos que você incorpore esses testes para aumentar a confiabilidade.
+ Para ilustrar a solução, este padrão fornece um arquivo de amostra `redshift.tf` que usa um arquivo de estado local do Terraform. No entanto, para ambientes de produção, recomendamos que você utilize um arquivo de estado remoto com um mecanismo de bloqueio para maior estabilidade e colaboração.
+ Alguns Serviços da AWS não estão disponíveis em todos Regiões da AWS. Para conferir a disponibilidade de uma região, consulte [Serviços da AWS by Region](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/). Para endpoints específicos, consulte [Service endpoints and quotas](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html) e clique no link correspondente ao serviço desejado.

**Versões do produto**

Esta solução foi desenvolvida e testada no [patch 179 do Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/cluster-versions.html#cluster-version-179).

**Repositório de código**

O código desse padrão está disponível no repositório GitHub [amazon-redshift-sql-deploy-terraform](https://github.com/aws-samples/amazon-redshift-sql-deploy-terraform).

## Arquitetura
<a name="execute-redshift-sql-queries-using-terraform-architecture"></a>

O diagrama apresentado a seguir ilustra como o Terraform gerencia os recursos do banco de dados do Amazon Redshift ao lidar tanto com consultas SQL não repetíveis quanto com consultas SQL repetíveis.

![\[Processo para o Terraform gerenciar os recursos do banco de dados do Amazon Redshift usando consultas SQL.\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/patterns/images/pattern-img/0f4467ac-761b-4b6b-a32f-e18a2ca2245d/images/3b6ff9e8-e3d1-48ed-9fa1-4b14f7d3d65b.png)


O diagrama mostra as seguintes etapas:

1. O Terraform aplica consultas SQL não repetíveis durante a implantação inicial do cluster do Amazon Redshift.

1. O desenvolvedor faz a confirmação das alterações nas consultas SQL repetíveis.

1. O Terraform monitora as mudanças nas consultas SQL repetíveis.

1. O Terraform aplica consultas SQL repetíveis no banco de dados do Amazon Redshift.

A solução fornecida por este padrão é desenvolvida com base no [módulo do Terraform para o Amazon Redshift](https://registry.terraform.io/modules/terraform-aws-modules/redshift/aws/latest). O módulo do Terraform provisiona um cluster e um banco de dados do Amazon Redshift. Para aprimorar o módulo, usamos `terraform_data` recursos, que invocam um script Python personalizado para executar consultas SQL usando a operação de API do Amazon Redshift. [ExecuteStatement](https://docs.aws.amazon.com/redshift-data/latest/APIReference/API_ExecuteStatement.html) Como resultado, o módulo é capaz de realizar o seguinte:
+ Implantar qualquer número de recursos de banco de dados usando consultas SQL após o provisionamento do banco de dados.
+ Realizar o monitoramento contínuo em busca de alterações nas consultas SQL repetíveis e aplicar essas mudanças usando o Terraform.

Para obter mais detalhes, consulte *Explicação passo a passo da solução* em [Informações adicionais](#execute-redshift-sql-queries-using-terraform-additional).

## Ferramentas
<a name="execute-redshift-sql-queries-using-terraform-tools"></a>

**Serviços da AWS**
+ O [Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/welcome.html) é um serviço totalmente gerenciado de data warehouse em escala de petabytes na Nuvem AWS.

**Outras ferramentas**
+ [O Terraform](https://www.terraform.io/) é uma ferramenta de infraestrutura como código (IaC) HashiCorp que ajuda você a criar e gerenciar recursos na nuvem e no local.
+ [Python](https://www.python.org/) é uma linguagem de programação de uso geral, empregada neste padrão para executar consultas SQL. 

## Práticas recomendadas
<a name="execute-redshift-sql-queries-using-terraform-best-practices"></a>
+ [Melhores práticas do Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/dg/best-practices.html)
+ [Using the Amazon Redshift Data API to interact with Amazon Redshift clusters](https://aws.amazon.com/blogs/big-data/using-the-amazon-redshift-data-api-to-interact-with-amazon-redshift-clusters/)

## Épicos
<a name="execute-redshift-sql-queries-using-terraform-epics"></a>

### Implementação da solução usando o Terraform
<a name="deploy-the-solution-using-terraform"></a>


| Tarefa | Description | Habilidades necessárias | 
| --- | --- | --- | 
| **Clone o repositório.** | Para clonar o repositório Git que contém o código do Terraform para o provisionamento de um cluster do Amazon Redshift, use o comando apresentado a seguir.<pre>git clone https://github.com/aws-samples/amazon-redshift-sql-deploy-terraform.git</pre> | DevOps engenheiro | 
| **Atualize as variáveis do Terraform.** | Para personalizar a implantação do cluster do Amazon Redshift de acordo com seus requisitos específicos, atualize os parâmetros apresentados a seguir no arquivo `terraform.tfvars`.<pre>region                    = "<AWS_REGION>"<br />cluster_identifier        = "<REDSHIFT_CLUSTER_IDENTIFIER>"<br />node_type                 = "<REDSHIFT_NODE_TYPE>"<br />number_of_nodes           = "<REDSHIFT_NODE_COUNT>"<br />database_name             = "<REDSHIFT_DB_NAME>"<br />subnet_ids                = "<REDSHIFT_SUBNET_IDS>"<br />vpc_security_group_ids    = "<REDSHIFT_SECURITY_GROUP_IDS>"<br />run_nonrepeatable_queries = true<br />run_repeatable_queries    = true<br />sql_path_bootstrap        = "<BOOTSTRAP_SQLS_PATH>"<br />sql_path_nonrepeatable    = "<NON-REPEATABLE_SQLS_PATH>"<br />sql_path_repeatable       = "<REPEATABLE_SQLS_PATH>"<br />sql_path_finalize         = "<FINALIZE_SQLS_PATH>"<br />create_random_password    = false<br />master_username           = "<REDSHIFT_MASTER_USERNAME>"</pre> | DevOps engenheiro | 
| Implante os recursos usando o Terraform. | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/patterns/execute-redshift-sql-queries-using-terraform.html) | DevOps engenheiro | 
| (Opcional) Execute consultas SQL adicionais. | O repositório de amostra fornece várias consultas SQL para fins de demonstração. Para executar suas próprias consultas SQL, adicione-as às seguintes pastas:`/bootstrap` `/nonrepeatable` `/repeatable` `/finalize` |  | 

### Monitoramento da execução das instruções SQL
<a name="monitor-the-execution-of-sql-statements"></a>


| Tarefa | Description | Habilidades necessárias | 
| --- | --- | --- | 
| Monitore a implantação das instruções SQL. | É possível monitorar os resultados das execuções SQL em um cluster do Amazon Redshift. Para obter exemplos de saída que mostram uma execução SQL com falha e uma execução com êxito, consulte as *Instruções SQL de exemplo* em [Informações adicionais](#execute-redshift-sql-queries-using-terraform-additional).  | DBA, engenheiro DevOps  | 
| Limpe recursos. | Para excluir todos os recursos implantados pelo Terraform, execute o comando apresentado a seguir.<pre>terraform destroy</pre> | DevOps engenheiro | 

### Validação dos resultados
<a name="validate-the-results"></a>


| Tarefa | Description | Habilidades necessárias | 
| --- | --- | --- | 
| Valide os dados no cluster do Amazon Redshift. | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/patterns/execute-redshift-sql-queries-using-terraform.html) | DBA, AWS DevOps | 

## Recursos relacionados
<a name="execute-redshift-sql-queries-using-terraform-resources"></a>

**AWS documentação**
+ [Clusters provisionados pelo Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html)
+ [Solução de problemas com a API de dados do Amazon Redshift](https://docs.aws.amazon.com/redshift/latest/mgmt/data-api-troubleshooting.html)

**Outros recursos**
+ [Command: apply](https://developer.hashicorp.com/terraform/cli/commands/apply) (documentação do Terraform)

## Mais informações
<a name="execute-redshift-sql-queries-using-terraform-additional"></a>

**Explicação passo a passo da solução**

Para usar a solução, você deve organizar suas consultas SQL do Amazon Redshift de uma forma específica. Todas as consultas SQL devem ser armazenadas em arquivos com a extensão `.sql`.

No exemplo de código fornecido com este padrão, as consultas SQL estão organizadas na estrutura de pastas apresentada a seguir. É possível modificar o código (`sql-queries.tf` e `sql-queries.py`) para funcionar com qualquer estrutura que atenda ao seu caso de uso específico.

```
/bootstrap
     |- Any # of files
     |- Any # of sub-folders
/nonrepeatable
     |- Any # of files
     |- Any # of sub-folders
/repeatable
     /udf
          |- Any # of files
          |- Any # of sub-folders
     /table
          |- Any # of files
          |- Any # of sub-folders
     /view
          |- Any # of files
          |- Any # of sub-folders
     /stored-procedure
          |- Any # of files
          |- Any # of sub-folders
/finalize
     |- Any # of files
     |- Any # of sub-folders
```

Dada a estrutura de pastas apresentada anteriormente, durante a implantação do cluster do Amazon Redshift, o Terraform executa as consultas na seguinte ordem:

1. `/bootstrap`

1. `/nonrepeatable`

1. `/repeatable`

1. `/finalize`

A pasta `/repeatable` contém quatro subpastas: `/udf`, `/table`, `/view` e `/stored-procedure`. Essas subpastas indicam a ordem em que o Terraform executa as consultas SQL.

O script em Python que executa as consultas SQL é `sql-queries.py`. Primeiro, o script realiza a leitura de todos os arquivos e subpastas de um diretório de origem específico, por exemplo, o parâmetro `sql_path_bootstrap`. Em seguida, o script executa as consultas chamando a operação da API do Amazon [ExecuteStatement](https://docs.aws.amazon.com/redshift-data/latest/APIReference/API_ExecuteStatement.html)Redshift. É possível ter uma ou mais consultas SQL em um arquivo. O trecho de código apresentado a seguir mostra a função em Python que executa as instruções SQL armazenadas em um arquivo em um cluster do Amazon Redshift.

```
def execute_sql_statement(filename, cluster_id, db_name, secret_arn, aws_region):
    """Execute SQL statements in a file"""
    redshift_client = boto3.client(
        'redshift-data', region_name=aws_region)
    contents = get_contents_from_file(filename),
    response = redshift_client.execute_statement(
        Sql=contents[0],
        ClusterIdentifier=cluster_id,
        Database=db_name,
        WithEvent=True,
        StatementName=filename,
        SecretArn=secret_arn
    )
    ...
```

O script do Terraform `sql-queries.tf` cria os recursos [terraform\$1data](https://developer.hashicorp.com/terraform/language/resources/terraform-data) que invocam o script `sql-queries.py`. Há um recurso `terraform_data` para cada uma das quatro pastas: `/bootstrap`, `/nonrepeatable`, `/repeatable` e `/finalize`. O trecho de código apresentado a seguir mostra o recurso `terraform_data` que executa as consultas SQL na pasta `/bootstrap`.

```
locals {
  program               = "${path.module}/sql-queries.py"
  redshift_cluster_name = try(aws_redshift_cluster.this[0].id, null)
}

resource "terraform_data" "run_bootstrap_queries" {
  count      = var.create && var.run_nonrepeatable_queries && (var.sql_path_bootstrap != "") && (var.snapshot_identifier == null) ? 1 : 0
  depends_on = [aws_redshift_cluster.this[0]]

  provisioner "local-exec" {
    command = "python3 ${local.program} ${var.sql_path_bootstrap} ${local.redshift_cluster_name} ${var.database_name} ${var.redshift_secret_arn} ${local.aws_region}"
  }
}
```

É possível controlar se as consultas serão executadas usando as variáveis apresentadas a seguir. Caso não deseje executar as consultas em `sql_path_bootstrap`, `sql_path_nonrepeatable`, `sql_path_repeatable` ou `sql_path_finalize`, defina seus valores como `""`.

```
  run_nonrepeatable_queries = true
  run_repeatable_queries    = true
  sql_path_bootstrap        = "src/redshift/bootstrap"
  sql_path_nonrepeatable    = "src/redshift/nonrepeatable"
  sql_path_repeatable       = "src/redshift/repeatable"
  sql_path_finalize         = "src/redshift/finalize"
```

Quando você executa `terraform apply`, o Terraform considera o recurso `terraform_data` adicionado após a conclusão do script, independentemente dos resultados do script. Se algumas consultas SQL falharem e você desejar executá-las novamente, é possível remover manualmente o recurso do estado do Terraform e executar `terraform apply` novamente. Por exemplo, o seguinte comando remove o recurso `run_bootstrap_queries` do estado do Terraform.

`terraform state rm module.redshift.terraform_data.run_bootstrap_queries[0]`

O exemplo de código apresentado a seguir mostra como o recurso `run_repeatable_queries` monitora alterações na pasta `repeatable` usando [sha256 hash](https://developer.hashicorp.com/terraform/language/functions/sha256). Se qualquer arquivo presente na pasta for atualizado, o Terraform marca todo o diretório para atualização. Em seguida, o Terraform executa novamente as consultas do diretório na próxima execução de `terraform apply`.

```
resource "terraform_data" "run_repeatable_queries" {
  count      = var.create_redshift && var.run_repeatable_queries && (var.sql_path_repeatable != "") ? 1 : 0
  depends_on = [terraform_data.run_nonrepeatable_queries]

  # Continuously monitor and apply changes in the repeatable folder
  triggers_replace = {
    dir_sha256 = sha256(join("", [for f in fileset("${var.sql_path_repeatable}", "**") : filesha256("${var.sql_path_repeatable}/${f}")]))
  }

  provisioner "local-exec" {
    command = "python3 ${local.sql_queries} ${var.sql_path_repeatable} ${local.redshift_cluster_name} ${var.database_name} ${var.redshift_secret_arn}"
  }
}
```

Para aprimorar o código, você pode implementar um mecanismo para detectar e aplicar alterações apenas nos arquivos que foram atualizados na pasta `repeatable`, em vez de aplicá-las a todos os arquivos indiscriminadamente.

**Instruções SQL de exemplo**

A saída a seguir apresenta uma execução SQL com falha, juntamente com a mensagem de erro correspondente.

```
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Executing: ["/bin/sh" "-c" "python3 modules/redshift/sql-queries.py src/redshift/nonrepeatable testcluster-1 db1 arn:aws:secretsmanager:us-east-1:XXXXXXXXXXXX:secret:/redshift/master_user/password-8RapGH us-east-1"]
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): -------------------------------------------------------------------
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): src/redshift/nonrepeatable/table/admin/admin.application_family.sql
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): -------------------------------------------------------------------
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Status: FAILED
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): SQL execution failed.
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec): Error message: ERROR: syntax error at or near ")"
module.redshift.terraform_data.run_nonrepeatable_queries[0] (local-exec):   Position: 244
module.redshift.terraform_data.run_nonrepeatable_queries[0]: Creation complete after 3s [id=ee50ba6c-11ae-5b64-7e2f-86fd8caa8b76]
```

A saída apresentada a seguir mostra uma execução SQL com êxito.

```
module.redshift.terraform_data.run_bootstrap_queries[0]: Provisioning with 'local-exec'...
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): Executing: ["/bin/sh" "-c" "python3 modules/redshift/sql-queries.py src/redshift/bootstrap testcluster-1 db1 arn:aws:secretsmanager:us-east-1:XXXXXXXXXXXX:secret:/redshift/master_user/password-8RapGH us-east-1"]
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): -------------------------------------------------------------------
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): src/redshift/bootstrap/db.sql
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): -------------------------------------------------------------------
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): Status: FINISHED
module.redshift.terraform_data.run_bootstrap_queries[0] (local-exec): SQL execution successful.
module.redshift.terraform_data.run_bootstrap_queries[0]: Creation complete after 2s [id=d565ef6d-be86-8afd-8e90-111e5ea4a1be]
```