1#!/usr/bin/python 2# 3# Copyright (c) 2019 Yuwei Zhou, <yuwzho@microsoft.com> 4# 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10 11ANSIBLE_METADATA = {'metadata_version': '1.1', 12 'status': ['preview'], 13 'supported_by': 'community'} 14 15 16DOCUMENTATION = ''' 17--- 18module: azure_rm_lock_info 19version_added: "2.9" 20short_description: Manage Azure locks 21description: 22 - Create, delete an Azure lock. 23options: 24 name: 25 description: 26 - Name of the lock. 27 type: str 28 required: true 29 managed_resource_id: 30 description: 31 - ID of the resource where need to manage the lock. 32 - Get this via facts module. 33 - Cannot be set mutual with I(resource_group). 34 - Manage subscription if both I(managed_resource_id) and I(resource_group) not defined. 35 - "'/subscriptions/{subscriptionId}' for subscriptions." 36 - "'/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}' for resource groups." 37 - "'/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{namespace}/{resourceType}/{resourceName}' for resources." 38 - Can get all locks with 'child scope' for this resource, use I(managed_resource_id) in response for further management. 39 type: str 40 resource_group: 41 description: 42 - Resource group name where need to manage the lock. 43 - The lock is in the resource group level. 44 - Cannot be set mutual with I(managed_resource_id). 45 - Query subscription if both I(managed_resource_id) and I(resource_group) not defined. 46 - Can get all locks with 'child scope' in this resource group, use the I(managed_resource_id) in response for further management. 47 type: str 48 49extends_documentation_fragment: 50 - azure 51 52author: 53 - Yuwei Zhou (@yuwzho) 54 55''' 56 57EXAMPLES = ''' 58- name: Get myLock details of myVM 59 azure_rm_lock_info: 60 name: myLock 61 managed_resource_id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM 62 63- name: List locks of myVM 64 azure_rm_lock_info: 65 managed_resource_id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM 66 67- name: List locks of myResourceGroup 68 azure_rm_lock_info: 69 resource_group: myResourceGroup 70 71- name: List locks of myResourceGroup 72 azure_rm_lock_info: 73 managed_resource_id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup 74 75- name: List locks of mySubscription 76 azure_rm_lock_info: 77 78- name: List locks of mySubscription 79 azure_rm_lock_info: 80 managed_resource_id: /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 81''' 82 83RETURN = ''' 84locks: 85 description: 86 - List of locks dicts. 87 returned: always 88 type: complex 89 contains: 90 id: 91 description: 92 - ID of the Lock. 93 returned: always 94 type: str 95 sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Authorization/locks/myLock" 96 name: 97 description: 98 - Name of the lock. 99 returned: always 100 type: str 101 sample: myLock 102 level: 103 description: 104 - Type level of the lock. 105 returned: always 106 type: str 107 sample: can_not_delete 108 notes: 109 description: 110 - Notes of the lock added by creator. 111 returned: always 112 type: str 113 sample: "This is a lock" 114''' # NOQA 115 116import json 117import re 118from ansible.module_utils.common.dict_transformations import _camel_to_snake 119from ansible.module_utils.azure_rm_common import AzureRMModuleBase 120from ansible.module_utils.azure_rm_common_rest import GenericRestClient 121 122try: 123 from msrestazure.azure_exceptions import CloudError 124except ImportError: 125 # This is handled in azure_rm_common 126 pass 127 128 129class AzureRMLockInfo(AzureRMModuleBase): 130 131 def __init__(self): 132 133 self.module_arg_spec = dict( 134 name=dict(type='str'), 135 resource_group=dict(type='str'), 136 managed_resource_id=dict(type='str') 137 ) 138 139 self.results = dict( 140 changed=False, 141 locks=[] 142 ) 143 144 mutually_exclusive = [['resource_group', 'managed_resource_id']] 145 146 self.name = None 147 self.resource_group = None 148 self.managed_resource_id = None 149 self._mgmt_client = None 150 self._query_parameters = {'api-version': '2016-09-01'} 151 self._header_parameters = {'Content-Type': 'application/json; charset=utf-8'} 152 153 super(AzureRMLockInfo, self).__init__(self.module_arg_spec, facts_module=True, mutually_exclusive=mutually_exclusive, supports_tags=False) 154 155 def exec_module(self, **kwargs): 156 157 is_old_facts = self.module._name == 'azure_rm_lock_facts' 158 if is_old_facts: 159 self.module.deprecate("The 'azure_rm_lock_facts' module has been renamed to 'azure_rm_lock_info'", version='2.13') 160 161 for key in self.module_arg_spec.keys(): 162 setattr(self, key, kwargs[key]) 163 164 self._mgmt_client = self.get_mgmt_svc_client(GenericRestClient, base_url=self._cloud_environment.endpoints.resource_manager) 165 changed = False 166 # construct scope id 167 scope = self.get_scope() 168 url = '/{0}/providers/Microsoft.Authorization/locks'.format(scope) 169 if self.name: 170 url = '{0}/{1}'.format(url, self.name) 171 locks = self.list_locks(url) 172 resp = locks.get('value') if 'value' in locks else [locks] 173 self.results['locks'] = [self.to_dict(x) for x in resp] 174 return self.results 175 176 def to_dict(self, lock): 177 resp = dict( 178 id=lock['id'], 179 name=lock['name'], 180 level=_camel_to_snake(lock['properties']['level']), 181 managed_resource_id=re.sub('/providers/Microsoft.Authorization/locks/.+', '', lock['id']) 182 ) 183 if lock['properties'].get('notes'): 184 resp['notes'] = lock['properties']['notes'] 185 if lock['properties'].get('owners'): 186 resp['owners'] = [x['application_id'] for x in lock['properties']['owners']] 187 return resp 188 189 def list_locks(self, url): 190 try: 191 resp = self._mgmt_client.query(url=url, 192 method='GET', 193 query_parameters=self._query_parameters, 194 header_parameters=self._header_parameters, 195 body=None, 196 expected_status_codes=[200], 197 polling_timeout=None, 198 polling_interval=None) 199 return json.loads(resp.text) 200 except CloudError as exc: 201 self.fail('Error when finding locks {0}: {1}'.format(url, exc.message)) 202 203 def get_scope(self): 204 ''' 205 Get the resource scope of the lock management. 206 '/subscriptions/{subscriptionId}' for subscriptions, 207 '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}' for resource groups, 208 '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/{namespace}/{resourceType}/{resourceName}' for resources. 209 ''' 210 if self.managed_resource_id: 211 return self.managed_resource_id 212 elif self.resource_group: 213 return '/subscriptions/{0}/resourcegroups/{1}'.format(self.subscription_id, self.resource_group) 214 else: 215 return '/subscriptions/{0}'.format(self.subscription_id) 216 217 218def main(): 219 AzureRMLockInfo() 220 221 222if __name__ == '__main__': 223 main() 224