View on GitHub

emersonprado.github.io

Página inicial
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.

  1. TL;DR
  2. Problema - mexer no código a cada mudança no ambiente
  3. Solução - cada macaco no seu galho
  4. Yaml
    1. O básico
    2. Aninhamento
    3. Referências
  5. 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:

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:

  1. 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.
  2. Para um valor simples, é só colocá-lo na linha seguinte. Poderia até ficar junto com os hífens, mas ficaria esquisito.
  3. Para um array, coloque cada item em uma linha, depois de um hífen e um espaço. É um mesmo. Lembre-se: YAML é exigente!
  4. 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!
  5. 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":

  1. Inicie objetos "externos" como sempre, mas sem o conteúdo - o item do array ou o valor do hash. Ou seja:
    1. Para um array "externo", coloque só o hífen
    2. Para um hash "externo", coloque só a chave e os dois pontos
  2. Indente objetos "internos" com dois espaços. São dois mesmo. Lembre-se: YAML é exigente!
  3. 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!
  4. 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:

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)!