В статье Terraform + vRA. Быстрый старт новый деплоймент создаётся из опубликованного в каталоге vRA элемента. Это самый простой способ работы с vRA из Terraform, но он недостаточно гибкий, — нет возможности изменить схему шаблона, деплойменты будут такими, как решил администратор Cloud Assembly. Terraform позволяет создавать свои облачные шаблоны и разворачивать из них деплойменты.
Terraform предлагает два способа работы с облачными шаблонами vRA 8 (раньше они назывались блюпринтами).
Динамическое описание шаблона из Terraform
Облачный шаблон генерируется на лету в процессе развертывания инфраструктуры через Terraform:
# main.tf 
provider "vra" {
  url           = var.url
  refresh_token = var.refresh_token
  insecure      = var.insecure
}
data "vra_project" "this" {
  name          = var.project_name
}
resource "random_id" "this" {
  byte_length   = 4
}
resource "vra_blueprint" "this" {
  name          = "${var.blueprint_name} (${random_id.this.hex})"
  description   = "Created by vRA terraform provider"
  project_id    = data.vra_project.this.id
  content = <<-EOT
formatVersion: 1
inputs:
  vmCount:
    type: integer
    minimum: 1
    maximum: 5
  vmSize:
    type: string
    title: VM size
    enum:
      - micro
      - small
      - medium
      - large
    default: small
  imageName:
    type: string
    enum:
      - CentOS_7
      - CentOS_8
      - Debian_9
      - Ubuntu_16
      - Ubuntu_18
      - Windows_2012
      - Windows_2016
    default: CentOS_7
    description: OS type
resources:
  Cloud_Network_1:
    type: Cloud.Network
    properties:
      networkType: existing
  Cloud_vSphere_Machine_1:
    type: Cloud.vSphere.Machine
    properties:
      count: '$${input.vmCount}'
      image: '$${input.imageName}'
      flavor: '$${input.vmSize}'
      cloudConfig: null
      name: 'vra-tf'
      customizationSpec: '$${starts_with(input.imageName, "Windows") ? "tmp-windows-vra" : "tmp-linux-vra"}'
      networks:
        - network: '$${resource.Cloud_Network_1.id}'
          assignment: static
  EOT
}
data "vra_blueprint" "this" {
  name              = vra_blueprint.this.name
  depends_on        = [vra_blueprint.this]
}
resource "vra_blueprint_version" "this" {
  blueprint_id      = data.vra_blueprint.this.id
  change_log        = "First version"
  description       = "Released from vRA terraform provider"
  release           = true
  version           = "1.0.1"
}
resource "vra_deployment" "this" {
  name              = "${var.deployment_name} - ${random_id.this.hex}"
  description       = var.deployment_descr
  project_id        = data.vra_project.this.id
  blueprint_id      = data.vra_blueprint.this.id
  blueprint_version = "1.0.1"
  inputs = {
    vmCount         = var.vm_count
    vmSize          = var.vm_flavor
    imageName       = var.image
  }
  timeouts {
    create          = "60m"
    delete          = "20m"
    update          = "30m"
  }
}
Все файлы доступны для загрузки на https://github.com/isas2.
В данном примере создаётся новый шаблон и получается его ID, код шаблона задаётся в параметре content, далее из шаблона разворачивается деплоймент. Обратите внимание, что переменные внутри кода шаблона экранированы дополнительным символом '$'.
Если позднее изменить этот шаблон (через Terraform или веб-интерфейс), то обновления развернутых из него деплойментов не произойдёт, обновится только сам облачный шаблон. Для применения обновлений используйте описание версии шаблона: resource "vra_blueprint_version". Также рекомендую все возможные параметры шаблонов выносить во входные параметры. Изменение значений входных параметров и номера версии шаблона в описании деплоймента приводит к его перенастройке.
Использование vra_blueprint имеет явное преимущество по сравнению с развёртываниями из элементов каталога: пользователь получает больше свободы, он самостоятельно описывает состав и параметры своих шаблонов.

Использование готовых шаблонов vRA
Описание шаблона внутри конфигурации Terraform сильно усложняет её код. Использование готовых облачных шаблонов - более удобный способ работы.
# main.tf 
provider "vra" {
  url               = var.url
  refresh_token     = var.refresh_token
  insecure          = var.insecure
}
data "vra_project" "this" {
  name              = var.project_name
}
resource "random_id" "this" {
  byte_length       = 4
}
data "vra_blueprint" "this" {
  name              = var.blueprint_name
}
resource "vra_deployment" "this" {
  name              = "${var.deployment_name} - ${random_id.this.hex}"
  description       = var.deployment_descr
  project_id        = data.vra_project.this.id
  blueprint_id      = data.vra_blueprint.this.id
  blueprint_version = var.blueprint_version
  inputs = {
    vmCount         = var.vm_count
    vmSize          = var.vm_flavor
    imageName       = var.image
  }
  timeouts {
    create          = "60m"
    delete          = "20m"
    update          = "30m"
  }
}
output "addresses_by_vmname" {
  description = "VM name and IP addresses from a vRA deployment"
  value = {
    for props in vra_deployment.this.resources.*.properties_json :
    jsondecode(props).resourceName => jsondecode(props).address
    if try(jsondecode(props).componentType, "") == "Cloud.vSphere.Machine"
  }
}
output "resource_properties_by_name" {
  description = "Properties of all resources by its name from a vRA deployment"
  value = {
    for rs in vra_deployment.this.resources :
    rs.name => jsondecode(rs.properties_json)
  }
}
Все файлы доступны для загрузки на https://github.com/isas2.
В данном примере в код добавлены выходные параметры Terraform:
- addresses_by_vmname после выполнения будет содержать имена всех VM и их IP-адреса:
 
addresses_by_vmname = {  
  "vra-tf-752" = "192.168.203.45"
  "vra-tf-753" = "192.168.203.44"
}
- resource_properties_by_name - содержит свойства всех ресурсов деплоймента.
 
Внимание! Для работы приведённых примеров пользователю vRA потребуются роли "Service Broker User" и "Cloud Assembly User".
Если необходимо генерировать облачные шаблоны на лету, не перегружая ими код Terraform, то vRA 8 умеет использовать GitLab в качестве внешнего хранилища шаблонов. При работе с GitLab Вам могут пригодиться следующие REST-запросы:
- /content/api/sourcecontrol/sync-all-requests - синхронизация всех внешних источников для данного проекта(-ов);
 - /content/api/sourcecontrol/sync-requests - синхронизация одного источника данных;
 - /content/api/sourcecontrol/sync-requests/{id} - получение статуса синхронизации по её ID. Возвращаемые значения статуса: "REQUESTED", "STARTED", "PROCESSING", "COMPLETED", "FAILED", "SKIPPED".