Planejar a estrutura do arquivo Bicep

Concluído

O Bicep proporciona a flexibilidade para você decidir como estruturar seu código. Nesta unidade, você conhecerá as maneiras de estruturar o código Bicep e a importância de um estilo consistente e um código Bicep claro e compreensível.

Qual ordem o código Bicep deve seguir?

Os modelos Bicep podem conter muitos elementos, incluindo parâmetros, variáveis, recursos, módulos, saídas e um targetScope para todo o modelo. O Bicep não impõe uma ordem para os elementos seguirem. No entanto, é importante considerar a ordem dos elementos a fim de garantir que o modelo seja claro e compreensível.

Há duas abordagens principais para ordenação do código:

  • Agrupar os elementos por tipo
  • Agrupar os elementos por recurso

Você e sua equipe devem chegar a um acordo em relação a uma delas e usá-la de modo consistente.

Agrupar os elementos por tipo

Você pode agrupar todos os elementos do mesmo tipo. Todos os seus parâmetros ficariam em um único lugar, geralmente na parte superior do arquivo. Depois, vêm as variáveis, seguidas dos recursos e dos módulos, e as saídas ficam no final. Por exemplo, você pode ter um arquivo Bicep que implanta um banco de dados SQL do Azure e uma conta de armazenamento.

Quando você agrupa os elementos por tipo, eles podem ter esta aparência:

Diagram showing elements grouped by element type. Parameters are grouped together, then variables, then resources, then outputs.

Dica

Se você seguir essa convenção, considere a possibilidade de colocar o targetScope no início do arquivo.

Essa ordenação faz sentido quando você está acostumado com outras linguagens de infraestrutura como código (por exemplo, a linguagem nos modelos do Azure Resource Manager). Isso também pode facilitar a compreensão do seu modelo, pois fica claro onde procurar tipos específicos de elementos. No entanto, em modelos mais longos, navegar e pular entre os elementos pode ser complicado.

Você ainda precisa decidir como ordenar os elementos dentro dessas categorias. É uma boa ideia agrupar os parâmetros relacionados. Por exemplo, todos os parâmetros referentes a uma conta de armazenamento ficam juntos e, dentro disso, os parâmetros de SKU da conta de armazenamento ficam juntos.

Da mesma forma, você pode agrupar recursos relacionados. Isso ajuda qualquer pessoa que use seu modelo a navegar rapidamente por ele e a entender as partes importantes do modelo.

Às vezes, você cria um modelo que implementa um recurso primário com vários recursos secundários de suporte. Por exemplo, você pode criar um modelo para implantar um site hospedado no Serviço de Aplicativo do Azure. O recurso primário é o aplicativo do Serviço de Aplicativo. Os recursos secundários no mesmo modelo podem incluir o Plano do Serviço de Aplicativo, a conta de armazenamento, uma instância do Application Insights e outros. Quando se tem um modelo como esse, é uma boa ideia colocar o recurso ou recursos principais na parte superior da seção de recursos do modelo, para que qualquer pessoa que abra o modelo possa identificar rapidamente a finalidade do modelo e encontrar os recursos importantes.

Agrupar os elementos por recurso

Como alternativa, você pode agrupar seus elementos com base no tipo de recursos que está implantando. Continuando com o exemplo anterior, você pode agrupar todos os parâmetros, as variáveis, as saídas e os recursos relacionados aos recursos do banco de dados SQL do Azure. Em seguida, você pode adicionar os parâmetros, as variáveis, os recursos e as saídas da conta de armazenamento, conforme mostrado aqui:

Diagram showing elements grouped by resource. Storage account elements are grouped, followed by Azure SQL database elements.

O agrupamento por recurso pode facilitar a leitura do modelo, pois todos os elementos necessários para um recurso específico estão em um só lugar. No entanto, isso dificulta a verificação rápida de como tipos de elementos específicos são declarados quando, por exemplo, você deseja revisar todos os seus parâmetros.

Você também precisa considerar como tratar os parâmetros e as variáveis comuns a vários recursos, como um parâmetro environmentType quando um mapa de configuração é usado. Os parâmetros e as variáveis comuns devem ser colocados juntos, geralmente no início do arquivo Bicep.

Dica

Considere se pode fazer mais sentido criar módulos para grupos de recursos relacionados e usar um modelo mais simples para combinar os módulos. Falaremos mais detalhadamente sobre os módulos Bicep nos roteiros de aprendizagem do Bicep.

Como o espaço em branco pode ajudar a criar a estrutura?

As linhas em branco, ou o espaço em branco, podem ajudar você a adicionar a estrutura visual ao modelo. Usando o espaço em branco com cautela, você pode agrupar as seções do código Bicep logicamente, o que, por sua vez, pode ajudar a esclarecer as relações entre os recursos. Para fazer isso, considere a possibilidade de adicionar uma linha em branco entre as seções principais, independentemente do estilo de agrupamento que preferir.

Como você define vários recursos semelhantes?

Com o Bicep, você pode usar loops para implantar recursos semelhantes por meio de uma só definição. Usando a palavra-chave for para definir loops de recursos, você pode tornar o código Bicep mais limpo e reduzir a duplicação desnecessária de definições de recursos. No futuro, quando você precisar alterar a definição dos recursos, bastará atualizar um local. Por padrão, quando o Azure Resource Manager implanta seus recursos, ele implanta todos os recursos no loop ao mesmo tempo, de modo que a implantação seja o mais eficiente possível.

Procure locais em que você defina vários recursos idênticos ou que tenham poucas diferenças nas propriedades. Em seguida, adicione uma variável para listar os recursos a serem criados, juntamente com as propriedades que diferem dos outros recursos. O seguinte exemplo usa um loop para definir um conjunto de contêineres do Azure Cosmos DB, cada um com um nome e uma chave de partição próprios:

var cosmosDBContainerDefinitions = [
  {
    name: 'customers'
    partitionKey: '/customerId'
  }
  {
    name: 'orders'
    partitionKey: '/orderId'
  }
  {
    name: 'products'
    partitionKey: '/productId'
  }
]

resource cosmosDBContainers 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2024-05-15' = [for cosmosDBContainerDefinition in cosmosDBContainerDefinitions: {
  parent: cosmosDBDatabase
  name: cosmosDBContainerDefinition.name
  properties: {
    resource: {
      id: cosmosDBContainerDefinition.name
      partitionKey: {
        kind: 'Hash'
        paths: [
          cosmosDBContainerDefinition.partitionKey
        ]
      }
    }
    options: {}
  }
}]

Como implantar recursos somente em determinados ambientes?

Às vezes, você define os recursos que devem ser implantados somente em ambientes específicos ou em determinadas condições. Usando a palavra-chave if, você pode implantar os recursos seletivamente com base em um valor de parâmetro, em uma variável de mapa de configuração ou em outra condição. O seguinte exemplo usa um mapa de configuração para implantar recursos de log para ambientes de produção, mas não para ambientes de teste:

var environmentConfigurationMap = {
  Production: {
    enableLogging: true
  }
  Test: {
    enableLogging: false
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = if (environmentConfigurationMap[environmentType].enableLogging) {
  name: logAnalyticsWorkspaceName
  location: location
}

resource cosmosDBAccountDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (environmentConfigurationMap[environmentType].enableLogging) {
  scope: cosmosDBAccount
  name: cosmosDBAccountDiagnosticSettingsName
  properties: {
    workspaceId: logAnalyticsWorkspace.id
    // ...
  }
}

Como expressar as dependências entre os recursos?

Em qualquer modelo Bicep complexo, é preciso expressar as dependências entre os recursos. Quando o Bicep compreende as dependências entre os recursos, ele as implanta na ordem correta.

O Bicep permite especificar explicitamente uma dependência por meio da propriedade dependsOn. No entanto, na maioria dos casos, é possível permitir que o Bicep detecte as dependências automaticamente. Quando você usa o nome simbólico de um recurso dentro de uma propriedade de outro, o Bicep detecta a relação. É melhor permitir que o Bicep gerencie-os sempre que possível. Dessa forma, quando você alterar seu modelo, o Bicep garantirá que as dependências estejam sempre corretas e você não adicionará nenhum código desnecessário que torne o modelo mais complicado e difícil de ser lido.

Como expressar as relações pai-filho?

O Azure Resource Manager e o Bicep trazem o conceito de recursos filho, que faz sentido somente quando eles são implantados dentro do contexto do pai. Por exemplo, um banco de dados SQL do Azure é filho de uma instância do servidor SQL. Há várias maneiras de definir os recursos filho, mas, na maioria dos casos, é uma boa ideia usar a propriedade parent. Isso ajuda o Bicep a entender o relacionamento para que possa fornecer validação no Visual Studio Code e deixa o relacionamento claro para qualquer outra pessoa que leia o modelo.

Como definir as propriedades de recursos?

Você precisa especificar os valores para as propriedades de recursos nos arquivos Bicep. É uma boa ideia ser cuidadoso quando você está embutindo valores em código nas definições de recursos. Se você souber que os valores não serão alterados, embuti-los em código poderá ser melhor do que usar outro parâmetro que dificulte o teste e o uso do modelo. No entanto, se for possível que os valores sejam alterados, considere defini-los como parâmetros ou variáveis para tornar seu código Bicep mais dinâmico e reutilizável.

Quando você embutir os valores em código, será bom verificar se eles são compreensíveis para outras pessoas. Por exemplo, se uma propriedade tiver que ser definida com um valor específico para que o recurso se comporte corretamente em sua solução, considere a possibilidade de criar uma variável bem nomeada que forneça uma explicação e, em seguida, atribua o valor usando a variável. Para situações em que um nome de variável não conte toda a história, considere a possibilidade de adicionar um comentário. Você verá mais sobre esses elementos posteriormente neste módulo.

Em algumas propriedades de recursos, para construir os valores automaticamente, é preciso criar expressões complexas que incluam funções e interpolação de cadeia de caracteres. Em geral, o código Bicep fica mais claro quando você declara variáveis e as referencia nos blocos de código do recurso.

Dica

Ao criar saídas, tente usar as propriedades do recurso sempre que puder. Evite incorporar suas próprias suposições sobre como os recursos funcionam, pois elas podem mudar com o tempo.

Por exemplo, se você precisar gerar a URL de um aplicativo do Serviço de Aplicativo, evite criar uma URL:

output hostname string = '${app.name}.azurewebsites.net'

A abordagem anterior será interrompida se o Serviço de Aplicativo alterar a forma como atribui nomes de host aos aplicativos ou se você implantar em ambientes do Azure que usam URLs diferentes.

Alternativamente, use a propriedade defaultHostname do recurso de aplicativo:

output hostname string = app.properties.defaultHostname

Como usar o controle de versão com eficiência?

Os sistemas de controle de versão, como o Git, podem ajudar a simplificar o seu trabalho quando estiver refatorando o código.

Como os sistemas de controle de versão são projetados para controlar as alterações nos seus arquivos, você pode usá-los para retornar facilmente a uma versão mais antiga do seu código se cometer um erro. É uma boa ideia fazer commit do seu trabalho com frequência para voltar ao ponto exato no tempo de que precisa.

O controle de versão também ajuda você a remover o código antigo dos arquivos Bicep. E se o código Bicep incluir uma definição de recurso da qual você não precisa mais? Você poderá precisar da definição novamente no futuro, e é uma tentação simplesmente removê-la do comentário e mantê-la no arquivo. Mas, na verdade, mantê-la nele apenas contribui para um arquivo Bicep desorganizado, dificultando para outras pessoas entenderem por que os recursos removidos da marca de comentário ainda estão nele.

Outra consideração é que é possível que alguém acidentalmente remova a marca de comentário da definição, com resultados imprevisíveis ou potencialmente adversos. Ao usar um sistema de controle de versão, você pode simplesmente remover a definição de recurso antiga. Se precisar da definição novamente no futuro, você poderá recuperá-la por meio do histórico do arquivo.