ansible failed with 'dict object' has no attribute 'ipAddress - azure

I was trying to provision an Azure application gateway by referring to the below document. https://learn.microsoft.com/en-us/azure/developer/ansible/application-gateway-configure?tabs=ansible but instead of containers I have used a virtual machine as my backend pool.
- name: Get info of backend server 1
azure_rm_resource_info:
api_version: '2018-04-01'
resource_group: "{{ resource_group }}"
provider: compute
resource_type: virtualmachines
resource_name: "{{ vm_1_name }}"
register: vm_1_output
- name: Create instance of Application Gateway
azure_rm_appgateway:
resource_group: "{{ resource_group }}"
name: "{{ appgw_name }}"
frontend_ip_configurations:
- public_ip_address: "publicip-{{env}}-{{appgw_name}}"
name: appGatewayFrontendIP
frontend_ports:
- port: 80
name: appGatewayFrontendPort
backend_address_pools:
- backend_addresses:
- ip_address: "{{ vm_1_output.response[0].properties.ipAddress.ip }}"
name: appGatewayBackendPool
But am getting the below error.
"The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'ipAddress'\n\nThe error appears to be in
I have tried changing the values IpAddress.ip, IPAddress.ip and private_ip_address.id but but still failing. Any help will be much appreciated.
Thanks

Looking at the return values for the azure_rm_resource_info module in Ansible, there doesn't seem to be an ipaddress property being returned in the response.
Use the azure_rm_networkinterface_info module to get facts for the network interface attached to the VM for retrieving the IP address. You should then be able to get to the IP with an expression similar to: networkinterface_output.networkinterfaces[0].ip_configurations[0].private_ip_address
Check this SO post that discusses a similar issue.

Related

ansible to provision azure loadbalncer with private ip

I was trying to provision an Azure load-balancer with only a private IP address in an existing subnet. I could accomplish this with the below code.
- name: create load balancer
azure_rm_loadbalancer:
resource_group: "{{resource_group_name}}"
name: my_new_lb
frontend_ip_configurations:
- name: frontendipconf0
private_ip_address:
private_ip_allocation_method: dynamic
subnet: /subscriptions/1234445sdffew11111111/resourceGroups/RG_NAME/providers/Microsoft.Network/virtualNetworks/vnet-stage/subnets/default
backend_address_pools:
- name: backend_pool1
probes:
- name: prob0
port: 80
load_balancing_rules:
- name: lbrbalancingrule0
frontend_ip_configuration: frontendipconf0
backend_address_pool: backend_pool1
frontend_port: 8000
backend_port: 443
probe: prob0
But is there a way we can provision a loadbalancer without providing a complete subnet id in the task file?
I could resolve the issue with the help of azure_rm_resource_info as well. Adding the script below.
azure_rm_resource_info:
api_version: '2018-08-01'
resource_group: "{{ resource_group_name }}"
provider: network
resource_type: virtualnetworks
resource_name: "{{ vnet_name }}"
subresource:
- type: subnets
name: "{{ subnet_name }}"
register: subnet
- name: create load balancer
azure_rm_loadbalancer:
resource_group: "{{resource_group_name}}"
name: lb_name
frontend_ip_configurations:
- name: frontendipconf0
private_ip_address:
private_ip_allocation_method: dynamic
subnet: "{{subnet.response[0].id }}"
If you want to provision the load balancer with a private IP address, then you must associate a subnet to the load balancer, so I think an existing subnet resource id is necessary. It's impossible not to provide a complete subnet id in the task file.
Update:
Here is the example to get the virtual network info:
- name: Get the Load Balancer info
azure_rm_virtualnetwork_info:
resource_group: "{{ resource_group_name }}"
name: "{{ vnet_name }}"
register: vnet
Then you can input the subnet id in the load balancer like this:
subnet: "{{ vnet.virtualnetworks[0].subnets[0].id }}"
You can get the VNet info and change the subnet you want to use. Please read the azure_rm_virtualnetwork_info example carefully.

Deploying multiple VM's with ansible

I'm learning ansible to create Linux VM's on azure and I used this sample playbook in this link (https://learn.microsoft.com/en-us/azure/developer/ansible/vm-configure?tabs=ansible) to create one VM on azure. If I want to deploy 10 VM's exactly like this with ansible-playbook how should I do it? Please help. Thanks in advance
Update: I tried it like this but the script fails after creating two public IP addresses.
- name: Create Azure VM
hosts: localhost
connection: local
tasks:
- name: Create resource group to hold VM
azure_rm_resourcegroup:
name: TestingResource
location: eastus
- name: Create virtual network
azure_rm_virtualnetwork:
resource_group: TestingResource
name: testingvnet
address_prefixes: "10.0.0.0/16"
- name: Add subnet
azure_rm_subnet:
resource_group: TestingResource
name: testingsubnet
address_prefix: "10.0.1.0/24"
virtual_network: testingvnet
- name: Create public IP address
azure_rm_publicipaddress:
resource_group: TestingResource
allocation_method: Static
name: "{{ item }}" #CHANGE HERE
loop:
- testingpublicIP2
- testingpublicIP3
register: output_ip_address
#- name: Dump public IP for VM which will be created
#debug:
#msg: "The public IP is {{ output_ip_address.state.ip_address }}."
- name: Create Network Security Group that allows SSH
azure_rm_securitygroup:
resource_group: TestingResource
name: TestingSecurityGroup
rules:
- name: SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 1001
direction: Inbound
- name: Create virtual network interface card
azure_rm_networkinterface:
resource_group: TestingResource
name: "{{ item }}" #CHANGE HERE
loop:
- TestingNIC2
- TestingNIC3
virtual_network: testingvnet
subnet: testingsubnet
public_ip_name: "{{ item }}" #CHANGE HERE
loop:
- testingpublicIP2
- testingpublicIP3
security_group: TestingSecurityGroup
- name: Create VM
azure_rm_virtualmachine:
resource_group: TestingResource
name: "{{ item }}" #CHANGE HERE VM NAME
loop:
- TestingResource2
- TestingResource3
vm_size: Standard_B2s
admin_username: admin
admin_password: password#123
ssh_password_enabled: true
network_interfaces: "{{ item }}" #CHANGE HERE
loop:
- TestingNIC2
- TestingNIC3
image:
offer: UbuntuServer
publisher: Canonical
sku: '18.04-LTS'
version: latest
You can use the loops function to create multiple VMs through ansible as you showed in the question, but you'd better use a list variable to loop so that you don't need to write all the elements every time. And the variables also can be used for other things like resource group name, location, and so on that use multiple times in the code. Here is the example:
- hosts: localhost
vars:
resource_group: myResourceGroup
...
tasks:
- name: Create resource group to hold VM
azure_rm_resourcegroup:
name: "{{ resource_group }}"
location: eastus
...
And the variable for the loop:
loop: "{{ var_list }}"
I found out it's quite easy with terraform to deploy multiple VM's on azure just by changing one variable in the configuration file, Here's the configuration file that i used (https://github.com/RichardPhilipsRoy/terraform-azure-linuxVMs)

Trying to Create a new Azure VM using a Snapshot of a managed disk with Ansible

I am trying to be able to deploy multiple machines using a GOLD vm snapshot through ansible. I need it to be like this:
- name: Creating Virtual Machine as requested.
azure_rm_virtualmachine:
resource_group: "{{ virtualMachineRG }}"
name: "{{ virtualMachineName }}"
vm_size: "{{ virtualMachineSize }}"
location: "{{ location }}"
managed_disk_type: "{{ managed_Disk_Type }}"
storage_account: "{{ storageAccount }}"
os_type: "{{ os_type }}"
image: "{{image}}"
os_disk_size_gb: "{{ os_disk_size_gb }}"
admin_username: "{{ adminUsername }}"
admin_password: "{{ adminPassword }}"
network_interfaces: "{{ virtualMachineName }}-nic"
I need the IMAGE or the entire disk to work similarly to creating a snapshot then creating a VM off the snapshot OR Create a clone of a managed disk and using that instead of the basic IMAGE of windows 10. This would be like having a snapshot that needs the same thing for 10 different VMs based on the request so its not the image that I would need but the GOLD Snapshot in place of the image which has operating system and everything installed. Is this doable? I have tried everything I can find through just searches and ansible documentation. This will deploy a new VM from the snapshot of the GOLD managed disk and this gets updated regularly and is set to the machine that controls the GOLD snapshot.

Ansible Azure Dynamic Inventory and Sharing variables between hosts in a single playbook

Problem: referencing a fact about a host ( in this case, the private ip ) from another host in a playbook using a wildcard only seems to work in the "Host" part of a playbook, not inside a task. vm_ubuntu* cannot be used in a task.
In a single playbook, I have a couple of hosts, and because the inventory is dynamic, I don't have the hostname ahead of time as Azure appends an identifier after it has been created.
I am using TF to create.
And using the Azure dynamic inventory method.
I am calling my playbook like this, where myazure_rm.yml is a bog standard azure dynamic inventory method, as of the time of this writing.
ansible-playbook -i ./myazure_rm.yml ./bwaf-playbook.yaml --key-file ~/.ssh/id_rsa --u azureuser
My playbook looks like this ( abbreviated ).
- hosts: vm_ubuntu*
tasks:
- name: housekeeping
set_fact:
vm_ubuntu_private_ip="{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"
#"
- debug: var=vm_ubuntu_private_ip
- hosts: vm_bwaf*
connection: local
vars:
vm_bwaf_private_ip: "{{private_ipv4_addresses | join }}"
vm_bwaf_public_ip: "{{ public_ipv4_addresses | join }}"
vm_ubuntu_private_ip: "{{ hostvars['vm_ubuntu*']['ip'] }}"
api_url: "http://{{ vm_bwaf_public_ip }}:8000/restapi/{{ api_version }}"
#"
I am answering my own question to get rep, and to to help others of course.
I also want to thank the person ( https://stackoverflow.com/users/4281353/mon ) who came up with this first, which appears in here: How do I set register a variable to persist between plays in ansible?
- name: "Save private ip to dummy host"
add_host:
name: "dummy_host"
ip: "{{ vm_ubuntu_private_ip }}"
And then this can be referenced in the other host in the playbook like this:
- hosts: vm_bwaf*
connection: local
vars:
vm_bwaf_private_ip: "{{private_ipv4_addresses | join }}"
vm_bwaf_public_ip: "{{ public_ipv4_addresses | join }}"
vm_ubuntu_private_ip: "{{ hostvars['dummy_host']['ip'] }}"

Get private IP for Azure scale set VMs in Ansible

How can you get the private IP for a VM in am Azure scale set in Ansible?
None of these seem to have the info:
azure_rm_virtualmachinescaleset_facts
azure_rm_virtualmachinescalesetinstance_facts
azure_rm_virtualmachine_facts
azure_rm_subnet_facts
azure_rm_networkinterface_facts
in order to get the IPs of my ScaleSet instances, I take the little detour via the PrivateDNS of Azure with auto-registration. As soon as the machines are available, they will be updated in the DNS.
Code Snippet:
- name: Fetch IPs from ScaleSet instances
hosts: localhost
connection: local
vars:
resource_group: "test-lbs1"
vmss_name: "vmss"
zone_name: "my.private.dns.zone"
tasks:
#############################################
# Fetch all Instances from Scaleset
#############################################
- name: List all of the instances
azure.azcollection.azure_rm_virtualmachinescalesetinstance_info:
resource_group: "{{ resource_group }}"
vmss_name: "{{ vmss_name }}"
register: __instances
#############################################
# Fetch IP from PrivateDNS Record
#############################################
- name: Get network interfaces
azure.azcollection.azure_rm_privatednsrecordset_info:
resource_group: "{{ resource_group }}"
zone_name: "{{ zone_name }}"
relative_name: "{{ item.computer_name }}"
record_type: A
with_items: "{{ __instances.instances }}"
register: __network_ips
- debug:
var: __network_ips

Resources