#!/usr/bin/python # # Copyright (c) 2016 Matt Davis, # Chris Houseknecht, # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # DOCUMENTATION = ''' --- module: azure_rm_resourcegroup version_added: "2.1" short_description: Manage Azure resource groups. description: - Create, update and delete a resource group. options: force: description: - Remove a resource group and all associated resources. Use with state 'absent' to delete a resource group that contains resources. default: false required: false location: description: - Azure location for the resource group. Required when creating a new resource group. Cannot be changed once resource group is created. required: false default: null name: description: - Name of the resource group. required: true state: description: - Assert the state of the resource group. Use 'present' to create or update and 'absent' to delete. When 'absent' a resource group containing resources will not be removed unless the force option is used. default: present choices: - absent - present required: false extends_documentation_fragment: - azure - azure_tags author: - "Chris Houseknecht (@chouseknecht)" - "Matt Davis (@nitzmahone)" ''' EXAMPLES = ''' - name: Create a resource group azure_rm_resourcegroup: name: Testing location: westus tags: testing: testing delete: never - name: Delete a resource group azure_rm_resourcegroup: name: Testing state: absent ''' RETURN = ''' contains_resources: description: Whether or not the resource group contains associated resources. type: bool sample: True state: description: Current state of the resource group. returned: always type: dict sample: { "id": "/subscriptions/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/Testing", "location": "westus", "name": "Testing", "provisioning_state": "Succeeded", "tags": { "delete": "on-exit", "testing": "no" } } ''' from ansible.module_utils.basic import * from ansible.module_utils.azure_rm_common import * try: from msrestazure.azure_exceptions import CloudError from azure.mgmt.resource.resources.models import ResourceGroup except ImportError: pass def resource_group_to_dict(rg): return dict( id=rg.id, name=rg.name, location=rg.location, tags=rg.tags, provisioning_state=rg.properties.provisioning_state ) class AzureRMResourceGroup(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( name=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), location=dict(type='str'), force=dict(type='bool', default=False) ) self.name = None self.state = None self.location = None self.tags = None self.force = None self.results = dict( changed=False, contains_resources=False, state=dict(), ) super(AzureRMResourceGroup, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=True) def exec_module(self, **kwargs): for key in self.module_arg_spec.keys() + ['tags']: setattr(self, key, kwargs[key]) results = dict() changed = False rg = None contains_resources = False try: self.log('Fetching resource group {0}'.format(self.name)) rg = self.rm_client.resource_groups.get(self.name) self.check_provisioning_state(rg, self.state) contains_resources = self.resources_exist() results = resource_group_to_dict(rg) if self.state == 'absent': self.log("CHANGED: resource group {0} exists but requested state is 'absent'".format(self.name)) changed = True elif self.state == 'present': update_tags, results['tags'] = self.update_tags(results['tags']) if update_tags: changed = True if self.location and self.location != results['location']: self.fail("Resource group '{0}' already exists in location '{1}' and cannot be " "moved.".format(self.name, results['location'])) except CloudError: self.log('Resource group {0} does not exist'.format(self.name)) if self.state == 'present': self.log("CHANGED: resource group {0} does not exist but requested state is " "'present'".format(self.name)) changed = True self.results['changed'] = changed self.results['state'] = results self.results['contains_resources'] = contains_resources if self.check_mode: return self.results if changed: if self.state == 'present': if not rg: # Create resource group self.log("Creating resource group {0}".format(self.name)) if not self.location: self.fail("Parameter error: location is required when creating a resource " "group.".format(self.name)) if self.name_exists(): self.fail("Error: a resource group with the name {0} already exists in your subscription." .format(self.name)) params = ResourceGroup( location=self.location, tags=self.tags ) else: # Update resource group params = ResourceGroup( location=results['location'], tags=results['tags'] ) self.results['state'] = self.create_or_update_resource_group(params) elif self.state == 'absent': if contains_resources and not self.force: self.fail("Error removing resource group {0}. Resources exist within the group.".format(self.name)) self.delete_resource_group() return self.results def create_or_update_resource_group(self, params): try: result = self.rm_client.resource_groups.create_or_update(self.name, params) except Exception as exc: self.fail("Error creating or updating resource group {0} - {1}".format(self.name, str(exc))) return resource_group_to_dict(result) def delete_resource_group(self): try: poller = self.rm_client.resource_groups.delete(self.name) self.get_poller_result(poller) except Exception as exc: self.fail("Error delete resource group {0} - {1}".format(self.name, str(exc))) # The delete operation doesn't return anything. # If we got here, assume all is good self.results['state']['status'] = 'Deleted' return True def resources_exist(self): found = False try: response = self.rm_client.resource_groups.list_resources(self.name) except Exception as exc: self.fail("Error checking for resource existence in {0} - {1}".format(self.name, str(exc))) for item in response: found = True break return found def name_exists(self): try: exists = self.rm_client.resource_groups.check_existence(self.name) except Exception as exc: self.fail("Error checking for existence of name {0} - {1}".format(self.name, str(exc))) return exists def main(): AzureRMResourceGroup() if __name__ == '__main__': main()