Adicionar parâmetros e saídas a módulos

Concluído

Cada módulo criado deve ter uma finalidade clara. Pense em um módulo como tendo um contrato. Ele aceita um conjunto de parâmetros, cria um conjunto de recursos e pode fornecer algumas saídas de volta para o modelo pai. Quem usa o módulo não precisa se preocupar com como ele funciona, apenas que ele faz o que é esperado.

Ao planejar um módulo, considere:

  • O que você precisa saber para ser capaz de atender à finalidade do módulo.
  • O que quem consome seu módulo espera que ele forneça.
  • O que quem consome seu módulo espera acessar como saídas.

Parâmetros do módulo

Pense nos parâmetros que seu módulo aceita e se cada parâmetro deve ser opcional ou obrigatório.

Quando você cria parâmetros para modelos, é uma boa prática adicionar parâmetros padrão sempre que possível. Nos módulos, nem sempre é tão importante adicionar parâmetros padrão, pois seu módulo será usado por um modelo pai que pode usar os próprios parâmetros padrão. Se você tiver parâmetros semelhantes em ambos os arquivos, ambos com valores padrão, poderá ser difícil para os usuários do modelo descobrir qual valor padrão será aplicado e impor consistência. Geralmente, é melhor deixar o valor padrão no modelo pai e removê-lo do módulo.

Você também deve pensar em como gerenciar parâmetros que controlam os SKUs para seus recursos e outras definições de configuração importantes. Quando você cria um modelo autônomo do Bicep, é comum inserir regras de negócio nele. Por exemplo: Quando implanto um ambiente de produção, a conta de armazenamento deve usar a camada GRS. Mas os módulos às vezes apresentam preocupações diferentes.

Se você estiver criando um módulo que precisa ser reutilizável e flexível, lembre-se de que as regras de negócios para cada modelo pai podem ser diferentes. Portanto, talvez não faça tanto sentido inserir regras de negócios em módulos genéricos. Considere definir as regras de negócios em seu modelo pai e, em seguida, passe explicitamente a configuração do módulo por meio de parâmetros.

No entanto, se você criar um módulo destinado a facilitar, para a sua organização, a implantação de recursos que se ajustam às suas necessidades específicas, faz sentido incluir regras de negócio para simplificar os modelos pai.

Ao incluir parâmetros em seu módulo, adicione uma descrição significativa usando o atributo @description:

@description('The name of the storage account to deploy.')
param storageAccountName string

Condições de uso

Uma das metas com a implantação de uma infraestrutura usando código como o Bicep é evitar o esforço de duplicação ou até mesmo criar vários modelos para fins semelhantes ou para os mesmos fins. Os recursos do Bicep oferecem uma poderosa caixa de ferramentas para criar módulos reutilizáveis que funcionam em várias situações. Você pode combinar recursos como módulos, expressões, valores de parâmetro padrão e condições para criar código reutilizável que oferece a flexibilidade necessária.

Suponha que você esteja criando um módulo que implanta uma conta do Azure Cosmos DB. Quando ele é implantado em seu ambiente de produção, você precisa configurar a conta para enviar os logs para um workspace do Log Analytics. Para configurar os logs a serem enviados ao Log Analytics, defina um recurso diagnosticSettings.

Você pode atingir seu requisito adicionando uma condição à definição de recurso, além de tornar o parâmetro de ID do workspace opcional adicionando um valor padrão:

param logAnalyticsWorkspaceId string = ''

resource cosmosDBAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = {
  // ...
}

resource cosmosDBAccountDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' =  if (logAnalyticsWorkspaceId != '') {
  scope: cosmosDBAccount
  name: 'route-logs-to-log-analytics'
  properties: {
    workspaceId: logAnalyticsWorkspaceId
    logs: [
      {
        category: 'DataPlaneRequests'
        enabled: true
      }
    ]
  }
}

Ao incluir esse módulo em um modelo do Bicep, você pode configurá-lo facilmente para enviar os logs da conta do Azure Cosmos DB para o Log Analytics definindo uma ID do workspace. Ou, se você não precisar de logs para o ambiente que está implantando, omita o parâmetro. Ele tem um valor padrão. O módulo encapsula a lógica necessária para fazer o certo para seus requisitos.

Dica

Lembre-se de testar se o modelo é válido para ambos os cenários. Quando a instrução if é avaliada como true ou false.

Saídas do módulo

Os módulos podem definir saídas. É uma boa ideia criar uma saída para as informações que o modelo pai pode precisar usar. Por exemplo, se o módulo definir uma conta de armazenamento, considere criar uma saída para o nome da conta de armazenamento para que o modelo pai possa acessá-la.

Aviso

Não use saídas para valores secretos. As saídas são registradas como parte do histórico de implantação, portanto, não são apropriadas para valores seguros. Em vez disso, você pode considerar uma das seguintes opções:

  • Use uma saída para fornecer o nome do recurso. Em seguida, o modelo pai pode criar um recurso existing com esse nome e pode procurar o valor seguro dinamicamente.
  • Escreva o valor em um segredo do Azure Key Vault. Faça com que o modelo pai leia o segredo do cofre quando necessário.

Um modelo pai pode usar saídas de módulo em variáveis, pode usar propriedades para outras definições de recurso ou pode expor variáveis e propriedades como saídas em si. Ao expor e usar saídas em todos os arquivos do Bicep, você pode criar conjuntos reutilizáveis de módulos do Bicep que podem ser compartilhados com sua equipe e reutilizados em várias implantações. Também é uma boa prática adicionar uma descrição significativa às saídas usando o atributo @description:

@description('The fully qualified Azure resource ID of the blob container within the storage account.')
output blobContainerResourceId string = storageAccount::blobService::container.id

Dica

Você também pode usar serviços dedicados para armazenar, gerenciar e acessar as configurações criadas pelo modelo do Bicep. O Key Vault é projetado para armazenar valores seguros. A Configuração de Aplicativos do Azure é projetada para armazenar outros valores (não seguros).

Encadear módulos juntos

É comum criar um arquivo do Bicep pai que compõe vários módulos juntos. Por exemplo, imagine que você esteja criando um modelo do Bicep para implantar máquinas virtuais que usam redes virtuais dedicadas. Você pode criar um módulo para definir uma rede virtual. Em seguida, você pode usar a ID do recurso de sub-rede da rede virtual como uma saída desse módulo e usá-la como uma entrada para o módulo da máquina virtual:

@description('Username for the virtual machine.')
param adminUsername string

@description('Password for the virtual machine.')
@minLength(12)
@secure()
param adminPassword string

module virtualNetwork 'modules/vnet.bicep' = {
  name: 'virtual-network'
}

module virtualMachine 'modules/vm.bicep' = {
  name: 'virtual-machine'
  params: {
    adminUsername: adminUsername
    adminPassword: adminPassword
    subnetResourceId: virtualNetwork.outputs.subnetResourceId
  }
}

Neste exemplo, nomes simbólicos são usados para a referência entre os módulos. Essa referência ajuda o Bicep a entender automaticamente as relações entre os módulos.

Como o Bicep entende que há uma dependência, ele implanta os módulos em sequência:

  1. O Bicep implanta tudo no módulo virtualNetwork.
  2. Se essa implantação for bem-sucedida, o Bicep acessará o valor de saída subnetResourceId e o passará para o módulo virtualMachine como um parâmetro.
  3. O Bicep implanta tudo no módulo virtualMachine.

Observação

Quando você depende de um módulo, o Bicep aguarda a implantação de todo o módulo ser finalizada. É importante se lembrar disso quando você planeja seus módulos. Se você criar um módulo que define um recurso que leva muito tempo para ser implantado, todos os outros recursos que dependem desse módulo aguardarão a implantação de todo o módulo ser finalizada.