0
votes

Tried setting up azure vms using terraform for the first time -

https://docs.microsoft.com/en-us/azure/developer/terraform/create-vm-cluster-with-infrastructure

 resource "azurerm_resource_group" "test" {  name     = "acctestrg" 
 location = "West US 2" }

 resource "azurerm_virtual_network" "test" {  name                =
 "acctvn"  address_space       = ["10.0.0.0/16"]  location            =
 azurerm_resource_group.test.location  resource_group_name =
 azurerm_resource_group.test.name }

 resource "azurerm_subnet" "test" {  name                 = "acctsub" 
 resource_group_name  = azurerm_resource_group.test.name 
 virtual_network_name = azurerm_virtual_network.test.name 
 address_prefix       = "10.0.2.0/24" }

 resource "azurerm_public_ip" "test" {  name                         =
 "publicIPForLB"  location                     =
 azurerm_resource_group.test.location  resource_group_name          =
 azurerm_resource_group.test.name  allocation_method            =
 "Static" }

 resource "azurerm_lb" "test" {  name                = "loadBalancer" 
 location            = azurerm_resource_group.test.location 
 resource_group_name = azurerm_resource_group.test.name

  frontend_ip_configuration {    name                 =
 "publicIPAddress"    public_ip_address_id = azurerm_public_ip.test.id 
 } }

 resource "azurerm_lb_backend_address_pool" "test" { 
 resource_group_name = azurerm_resource_group.test.name 
 loadbalancer_id     = azurerm_lb.test.id  name                =
 "BackEndAddressPool" }

 resource "azurerm_network_interface" "test" {  count               = 2
 name                = "acctni${count.index}"  location            =
 azurerm_resource_group.test.location  resource_group_name =
 azurerm_resource_group.test.name

  ip_configuration {    name                          =
 "testConfiguration"    subnet_id                     =
 azurerm_subnet.test.id    private_ip_address_allocation = "dynamic"  }
 }

 resource "azurerm_managed_disk" "test" {  count                = 2 
 name                 = "datadisk_existing_${count.index}"  location   
 = azurerm_resource_group.test.location  resource_group_name  = azurerm_resource_group.test.name  storage_account_type =
 "Standard_LRS"  create_option        = "Empty"  disk_size_gb         =
 "1023" }

 resource "azurerm_availability_set" "avset" {  name                   
 = "avset"  location                     = azurerm_resource_group.test.location  resource_group_name          =
 azurerm_resource_group.test.name  platform_fault_domain_count  = 2 
 platform_update_domain_count = 2  managed                      = true
 }

 resource "azurerm_virtual_machine" "test" {  count                 = 2
 name                  = "acctvm${count.index}"  location             
 = azurerm_resource_group.test.location  availability_set_id   = azurerm_availability_set.avset.id  resource_group_name   =
 azurerm_resource_group.test.name  network_interface_ids =
 [element(azurerm_network_interface.test.*.id, count.index)]  vm_size  
 = "Standard_DS1_v2"

  # Uncomment this line to delete the OS disk automatically when
 deleting the VM  # delete_os_disk_on_termination = true

  # Uncomment this line to delete the data disks automatically when
 deleting the VM  # delete_data_disks_on_termination = true

  storage_image_reference {    publisher = "Canonical"    offer     =
 "UbuntuServer"    sku       = "16.04-LTS"    version   = "latest"  }

  storage_os_disk {    name              = "myosdisk${count.index}"   
 caching           = "ReadWrite"    create_option     = "FromImage"   
 managed_disk_type = "Standard_LRS"  }

  # Optional data disks  storage_data_disk {    name              =
 "datadisk_new_${count.index}"    managed_disk_type = "Standard_LRS"   
 create_option     = "Empty"    lun               = 0    disk_size_gb  
 = "1023"  }

  storage_data_disk {    name            =
 element(azurerm_managed_disk.test.*.name, count.index)   
 managed_disk_id = element(azurerm_managed_disk.test.*.id, count.index)
 create_option   = "Attach"    lun             = 1    disk_size_gb    =
 element(azurerm_managed_disk.test.*.disk_size_gb, count.index)  }

  os_profile {    computer_name  = "hostname"    admin_username =
 "testadmin"    admin_password = "Password1234!"  }

  os_profile_linux_config {    disable_password_authentication = false 
 }

  tags = {    environment = "staging"  } }

Still not able to set up.

Running terraform plan always gives the following error - Abhisheks-MBP:first abhisheksingh$ terraform plan

Error: "features": required field is not set

As suggested by number of stackoverflow questions, I tried adding providers block with empty features section. I also tried to pin the version down to 2.0.0. However , everytime version 2.8.0 gets downloaded and the same error comes up again. Does anyone know what needs to be done ? This is pretty frustrating for someone who is trying for the first time. What kind of tutorial is that it lets you struggle so much the first time itself.

Abhisheks-MBP:first abhisheksingh$ terraform -v Terraform v0.12.24 + provider.azurerm v2.8.0

I even added the following section to the tf file -

Azure Provider/s provider "azurerm" { version = "=2.0.0" features {} }

But does not help!!

Why do I get "required field is not set" when following the Tutorial: Create an Azure VM cluster with Terraform and HCL?

2

2 Answers

1
votes

I can confirm this tutorial works, I also matched your Terraform and Azure provider versions:

Terraform v0.12.24
+ provider.azurerm v2.8.0

The error would indicate that Terraform did not find provider block specified, and your provided code sample does not set one, so assuming you gave the whole main.tf file I'd suggested adding the following block to the top of your main.tf file

provider "azurerm" {
  version = "2.8.0"
  features {}
}

Also please make sure your are in the directory where main.tf is located when you initiate terraform init and terraform plan

I had success with the following main.tf

provider "azurerm" {
  version = "2.8.0"
  features {}
}

resource "azurerm_resource_group" "test" {
  name     = "acctestrg"
  location = "West US 2"
}

resource "azurerm_virtual_network" "test" {
  name                = "acctvn"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_subnet" "test" {
  name                 = "acctsub"
  resource_group_name  = azurerm_resource_group.test.name
  virtual_network_name = azurerm_virtual_network.test.name
  address_prefix       = "10.0.2.0/24"
}

resource "azurerm_public_ip" "test" {
  name                = "publicIPForLB"
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name
  allocation_method   = "Static"
}

resource "azurerm_lb" "test" {
  name                = "loadBalancer"
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name
  frontend_ip_configuration {
    name                 = "publicIPAddress"
    public_ip_address_id = azurerm_public_ip.test.id
  }
}

resource "azurerm_lb_backend_address_pool" "test" {
  resource_group_name = azurerm_resource_group.test.name
  loadbalancer_id     = azurerm_lb.test.id
  name                = "BackEndAddressPool"
}


resource "azurerm_network_interface" "test" {
  count               = 2
  name                = "acctni${count.index}"
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name
  ip_configuration {
    name                          = "testConfiguration"
    subnet_id                     = azurerm_subnet.test.id
    private_ip_address_allocation = "dynamic"
  }
}


resource "azurerm_managed_disk" "test" {
  count                = 2
  name                 = "datadisk_existing_${count.index}"
  location             = azurerm_resource_group.test.location
  resource_group_name  = azurerm_resource_group.test.name
  storage_account_type = "Standard_LRS"
  create_option        = "Empty"
  disk_size_gb         = "1023"
}

resource "azurerm_availability_set" "avset" {
  name                         = "avset"
  location                     = azurerm_resource_group.test.location
  resource_group_name          = azurerm_resource_group.test.name
  platform_fault_domain_count  = 2
  platform_update_domain_count = 2
  managed                      = true
}


resource "azurerm_virtual_machine" "test" {
  count                 = 2
  name                  = "acctvm${count.index}"
  location              = azurerm_resource_group.test.location
  availability_set_id   = azurerm_availability_set.avset.id
  resource_group_name   = azurerm_resource_group.test.name
  network_interface_ids = [element(azurerm_network_interface.test.*.id, count.index)]
  vm_size               = "Standard_DS1_v2"
  # Uncomment this line to delete the OS disk automatically when deleting the VM  
  delete_os_disk_on_termination = true
  # Uncomment this line to delete the data disks automatically when deleting the VM  
  delete_data_disks_on_termination = true
  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "16.04-LTS"
    version   = "latest"
  }
  storage_os_disk {
    name              = "myosdisk${count.index}"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }
  # Optional data disks  
  storage_data_disk {
    name              = "datadisk_new_${count.index}"
    managed_disk_type = "Standard_LRS"
    create_option     = "Empty"
    lun               = 0
    disk_size_gb      = "1023"
  }
  storage_data_disk {
    name            = element(azurerm_managed_disk.test.*.name, count.index)
    managed_disk_id = element(azurerm_managed_disk.test.*.id, count.index)
    create_option   = "Attach"
    lun             = 1
    disk_size_gb    = element(azurerm_managed_disk.test.*.disk_size_gb, count.index)
  }
  os_profile {
    computer_name  = "hostname"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = { environment = "staging" }
}

Make sure you use terraform init to download correct provider version.

Hope this helps.

0
votes

You are not alone, I got the same error...
if I just copy paste the code from that tutorial I get:
Error: "features": required field is not set

What I see is that it does not have a provider block, it should be something like:

provider "azurerm" { 
    # The "feature" block is required for AzureRM provider 2.x. 
    # If you are using version 1.x, the "features" block is not allowed.
    version = "~>2.0"
    features {}
}

Other tutorials do cover that:

https://docs.microsoft.com/en-us/azure/developer/terraform/create-vm-cluster-module#set-up-authentication-with-azure

Educated guess no one is really reviewing those tutorials.
All you can do is leave them a comment to let them know...