Repository: ansible/ansible

Issue:
Azure image cannot be created with tag
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report


##### COMPONENT NAME
<!---
Insert below this comment the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
azure_rm_image

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
2.5.0
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: localhost
  vars:
    resource_group: testimage001
  tasks:
  - name: Create storage account name
    set_fact:
        storage_account: "{{ resource_group | hash('md5') | truncate(24, True, '') }}"

  - name: Create storage account
    azure_rm_storageaccount:
        resource_group: "{{ resource_group }}"
        name: "{{ storage_account }}"
        account_type: Standard_LRS

  - name: Create virtual network
    azure_rm_virtualnetwork:
        resource_group: "{{ resource_group }}"
        name: testvm001
        address_prefixes: "10.10.0.0/16"

  - name: Add subnet
    azure_rm_subnet:
        resource_group: "{{ resource_group }}"
        name: testvm001
        address_prefix: "10.10.0.0/24"
        virtual_network: testvm001

  - name: Create public ip
    azure_rm_publicipaddress:
        resource_group: "{{ resource_group }}"
        allocation_method: Static
        name: testvm001

  - name: Create security group
    azure_rm_securitygroup:
        resource_group: "{{ resource_group }}"
        name: testvm001

  - name: Create NIC
    azure_rm_networkinterface:
        resource_group: "{{ resource_group }}"
        name: testvm001
        virtual_network: testvm001
        subnet: testvm001
        public_ip_name: testvm001
        security_group: testvm001

  - name: Create virtual machine
    azure_rm_virtualmachine:
        resource_group: "{{ resource_group }}"
        name: testvm002
        vm_size: Standard_A0
        storage_account: "{{ storage_account }}"
        storage_container: testvm001
        storage_blob: testvm001.vhd
        admin_username: adminuser
        admin_password: Password123!
        os_type: Linux
        network_interfaces: testvm001
        image:
            offer: UbuntuServer
            publisher: Canonical
            sku: 16.04-LTS
            version: latest

  - name: Deallocate the virtual machine
    azure_rm_virtualmachine:
        resource_group: "{{ resource_group }}"
        name: testvm002
        allocated: no 
        vm_size: Standard_A0

  - name: Start the virtual machine
    azure_rm_virtualmachine:
        resource_group: "{{ resource_group }}"
        name: testvm002
        vm_size: Standard_A0

  - name: Create an image from VM
    azure_rm_image:
        resource_group: "{{ resource_group }}"
        source: "https://{{ storage_account }}.blob.core.windows.net/testvm001/testvm001.vhd"
        name: testimage001
        os_type: Linux
    tags:
        foo: bar
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

tags can be see on the Azure portal

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:
+label easyfix

Resolving patch:
diff --git a/lib/ansible/modules/cloud/azure/azure_rm_image.py b/lib/ansible/modules/cloud/azure/azure_rm_image.py
--- a/lib/ansible/modules/cloud/azure/azure_rm_image.py
+++ b/lib/ansible/modules/cloud/azure/azure_rm_image.py
@@ -135,13 +135,12 @@ def __init__(self):
         self.source = None
         self.data_disk_sources = None
         self.os_type = None
-        self.tags = None
 
         super(AzureRMImage, self).__init__(self.module_arg_spec, supports_check_mode=True, required_if=required_if)
 
     def exec_module(self, **kwargs):
 
-        for key in self.module_arg_spec:
+        for key in list(self.module_arg_spec.keys()) + ['tags']:
             setattr(self, key, kwargs[key])
 
         results = None
@@ -158,7 +157,11 @@ def exec_module(self, **kwargs):
         if image:
             self.check_provisioning_state(image, self.state)
             results = image.id
-            # update is not supported
+            # update is not supported except for tags
+            update_tags, tags = self.update_tags(image.tags)
+            if update_tags:
+                changed = True
+                self.tags = tags
             if self.state == 'absent':
                 changed = True
         # the image does not exist and create a new one
@@ -176,7 +179,7 @@ def exec_module(self, **kwargs):
                 if vm:
                     if self.data_disk_sources:
                         self.fail('data_disk_sources is not allowed when capturing image from vm')
-                    image_instance = self.compute_models.Image(self.location, source_virtual_machine=self.compute_models.SubResource(vm.id))
+                    image_instance = self.compute_models.Image(self.location, source_virtual_machine=self.compute_models.SubResource(vm.id), tags=self.tags)
                 else:
                     if not self.os_type:
                         self.fail('os_type is required to create the image')


Test patch: