English
Vagrantfiles eficientes – Parte 3 – Separação de código e dados
Emerson Prado - 14/01/2020
Na parte 2 desta série de artigos, nos livramos de muita repetição de código (e de muito lugar bom pra erros de digitação) usando arrays, hashes, laços e condicionais. Agora, vamos fazer uma pausa nos Vagrantfiles e conferir um formato de arquivo que vai ajudar muito quando voltarmos a eles.
- TL;DR
- Problema - mexer no código a cada mudança no ambiente
- Solução - cada macaco no seu galho
- Yaml
- Próximo passo
TL;DR
Se você já conhece arquivos YAML, talvez você possa pular esta parte dos artigos, e fazer tudo funcionar com o resumo abaixo.
Vagrantfiles com código e dados misturados bagunçam a manutenção e o versionamento. Podemos deixar tudo mais simples e organizado colocando os dados em arquivos YAML e carregá-los no Vagrantfile.
Arquivos YAML podem armazenar objetos como strings, números, arrays e hashes. Estes dois últimos podem ser aninhados. Seguem exemplos pra refrescar a memória (cada exemplo é um arquivo).
--- # Comece uma linha com 3 hífens, informando ao SO que é um arquivo YAML # PRECISA ser a PRIMEIRA linha e TRÊS hífens. Exatamente. # Cerquilhas (#) indicam comentários. No fim da linha ou em linha própria. # Este arquivo contém um número 3.14 --- # Outro arquivo Este arquivo contém esta string --- # Array (itens podem ter classes variadas) - Um - -3.14 - Blowin' in the Wind # Itens PRECISAM ser precedidos por UM hífen e UM espaço. Exatamente. --- # Hash (chaves e valores podem ter classes variadas) Um: 1 2: Dois Chave multi-palavra: Valor multi-palavra "Chave com dois pontos: coloque entre aspas": Valor # Chaves PRECISAM ter NADA antes e dois pontos depois. Exatamente. # VALORES PRECISAM ser separados das chaves por espaços. --- # Aninhamento a partir de um array - # O item 1 do array externo é o array intermediário abaixo - item_1_1 - item_1_2 - # Mais aninhamento # O item 3 do array intermediário é o array interno abaixo - item_1_3_1 - item_1_3_2 - # Aninhando hashes em arrays chave_1_4_1: valor_1_4_1 chave_1_4_2: valor_1_4_2 - # Item 2 do array externo ... --- # Aninhamento a partir de um hash chave_1: # O valor do elemento 1 do hash externo é o hash intermediário abaixo chave_1_1: valor_1_1 chave_1_2: valor_1_1 chave_1_3: # Mais aninhamento # O valor do elemento 3 do hash intermediário é o hash interno abaixo chave_1_3_1: valor_1_3_1 chave_1_3_2: valor_1_3_2 chave_1_4: # Aninhando arrays em hashes - item_1_4_1 - item_1_4_2 chave_2: # Elemento 2 do array externo ...
Pra integração com o Vagrantfile, vá para a parte 4 (em breve).
Problema - mexer no código a cada mudança no ambiente
Seu ambiente vai mudar. Ponto final. Talvez você precise testar uma versão nova de uma aplicação, ou depurar algum problema nela, ou testá-la em outras opções de SO, ou atualizar boxes, etc. Esse é, afinal, um dos principais motivos pra você usar o Vagrant. Na forma corriqueira de uso do Vagrant, cada mudança implica em editar o Vagrantfile. Isto traz algumas dores de cabeça:
- Você pode acabar tendo um Vagrantfile enorme, com tudo dentro. Mudar alguma coisa nele vai ficando cada vez mais difícil.
- Quando você precisa mexer no código, você está cercado de dados. E vice-versa. É mais difícil focar em um - e mais fácil "esbarrar" no outro.
- O reúso de Vagrantfiles se torna trabalhoso - é necessário copiar e colar Vagrantfiles e editar manualmente as diferenças.
- O versionamento fica confuso - pra qualquer mudança, seu sistema de versionamento sempre indicará a mesma alteração: o Vagrantfile.
Solução - cada macaco no seu galho
Se o problema é código e dados misturados, a solução é simples: basta separá-los.
Como o intuito do Vagrantfile é conter o código do seu ambiente, ele já é o lugar certo pro código. Então, os dados têm que ir pra outro lugar.
Uma boa forma de armazenar os dados é, claro, em arquivos com formato próprio para armazenar dados. Pra sorte nossa, existe um formato que é amigo íntimo do Ruby.
Yaml
YAML é um formato de arquivo de dados estruturados que pode armazenar um objeto Ruby, que pode ser um valor simples, um array, um hash, ou arrays/hashes aninhados, sem muita dor de cabeça (desde que você se acostume com o formato exigente).
Então, com os dados em arquivos YAML, fica fácil carregá-los no Vagrantfile. Assim, o Vagrantfile terá apenas código, e os arquivos YAML, só dados. Aplausos!
O Básico
O formato do conteúdo do arquivo YAML depende principalmente do tipo de objeto armazenado:
- Comece com 3 hífens na primeira linha. É isso que informa ao SO que o arquivo é YAML. Não é uma exigência, mas é altamente recomendado.
- Para um valor simples, é só colocá-lo na linha seguinte. Poderia até ficar junto com os hífens, mas ficaria esquisito.
- Para um array, coloque cada item em uma linha, depois de um hífen e um espaço. É um mesmo. Lembre-se: YAML é exigente!
- Para um hash, coloque cada chave no começo de uma linha, seguida de dois pontos, depois espaço(s), e então o valor. É no começo mesmo, com espaço(s) mesmo entre os dois pontos e o valor. Lembre-se: YAML é exigente!
- Coloque comentários depois de uma cerquilha (#).
Exemplos (cada um é um arquivo)
--- # Um número 3.14 --- # Uma string Olá, mundo! --- # Um array (as classes dos itens podem variar) - Um - -3.14 - Blowin' in the Wind --- # Um hash (as classes das chaves e valores podem variar) Um: 1 2: Dois Chave multi-palavra: Valor multi-palavra "Chave com dois pontos: coloque entre aspas": Valor
Aninhamento
Assim como arrays e hashes podem ser aninhados em objetos Ruby, também podem em arquivos YAML. O que indica o aninhamento é a indentação, e alguma atenção especial aos objetos "externos":
- Inicie objetos "externos" como sempre, mas sem o conteúdo - o item do array ou o valor do hash. Ou seja:
- Para um array "externo", coloque só o hífen
- Para um hash "externo", coloque só a chave e os dois pontos
- Indente objetos "internos" com dois espaços. São dois mesmo. Lembre-se: YAML é exigente!
- Para aninhar mais, faça exatamente a mesma coisa, mas indentando com dois espaços adicionais para cada nível de aninhamento. São dois mesmo. Lembre-se: YAML é exigente!
- Nunca indente com tabulações. De jeito nenhum! Não sei se já avisei, mas YAML é exigente!
Exemplos (cada um é um arquivo)
--- # Aninhando arrays - # O item 1 do array externo é o array intermediário abaixo - item_1_1 - item_1_2 - # Mais aninhamento # O item 3 do array intermediário é o array interno abaixo - item_3_1 - item_3_2 - # Aninhando hashes em arrays chave_1_4_1: valor_1_4_1 chave_1_4_2: valor_1_4_2 - # Item 2 do array externo ... --- # Aninhando hashes chave_1: # O valor do elemento 1 do hash externo é o hash intermediário abaixo chave_1_1: valor_1_1 chave_1_2: valor_1_1 chave_1_3: # Mais aninhamento # O valor do elemento 3 do hash intermediário é o hash interno abaixo chave_1_3_1: valor_1_3_1 chave_1_3_2: valor_1_3_2 chave_1_4: # Aninhando arrays em hashes - item_1_4_1 - item_1_4_2 chave_2: # Elemento 2 do hash externo ... --- # Essa viagem é realmente necessária? chave_1: # O valor deste elemento é o array abaixo - # O valor deste item é o hash abaixo chave_1_1_1: # O valor deste elemento é o array abaixo - item_1_1_1_1 - item_1_1_1_2 chave_1_1_2: - item_1_1_2_1 - item_1_1_2_2 - chave_1_2_1: ... chave_2: ...
Referências
Dicas pra aprender YAML de verdade:
- Esta ótima introdução da documentação do Ansible. É uma introdução bem abrangente, mas simples e de fácil leitura.
- Um tutorial completo do Tutorials Point. Passa por tudo (eu acho).
- O manual oficial. Mantenha sempre manuais oficiais por perto.
Próximo passo
Agora, é só pegar o hash enorme da parte 2, colocar em um arquivo YAML, e carregar o objeto no Vagrantfile. Vamos à parte 4 (em breve)!