diff --git a/lib/ansible/modules/cloud/azure/azure_rm_softwareupdateconfiguration.py b/lib/ansible/modules/cloud/azure/azure_rm_softwareupdateconfiguration.py new file mode 100644 index 00000000000000..df4875dd37d5e3 --- /dev/null +++ b/lib/ansible/modules/cloud/azure/azure_rm_softwareupdateconfiguration.py @@ -0,0 +1,796 @@ +#!/usr/bin/python +# +# Copyright (C) 2019 audevbot +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file at +# https://github.com/Azure/magic-module-specs +# +# ---------------------------------------------------------------------------- + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: azure_rm_softwareupdateconfiguration +version_added: "2.9" +short_description: Manage Azure SoftwareUpdateConfiguration instance. +description: + - Create, update and delete instance of Azure Software Update Configuration. + +options: + resource_group: + description: + - Name of an Azure Resource group. + required: true + type: str + name: + description: + - The name of the software update configuration to be created. + required: true + type: str + automation_account_name: + description: + - The name of the automation account. + required: true + type: str + client_request_id: + description: + - Identifies this specific client request. + type: str + error: + description: + - Details of provisioning error. + type: dict + suboptions: + code: + description: + - Error code. + type: str + message: + description: + - Error message indicating why the operation failed. + type: str + schedule_info: + description: + - Schedule information for the Software update configuration. + required: true + type: dict + suboptions: + start_time: + description: + - Gets or sets the start time of the schedule. + type: str + expiry_time: + description: + - Gets or sets the end time of the schedule. + type: str + expiry_time_offset_minutes: + description: + - Gets or sets the expiry time's offset in minutes. + type: int + is_enabled: + description: + - Gets or sets a value indicating whether this schedule is enabled. + type: bool + next_run: + description: + - Gets or sets the next run time of the schedule. + type: str + next_run_offset_minutes: + description: + - Gets or sets the next run time's offset in minutes. + type: int + interval: + description: + - Gets or sets the interval of the schedule. + type: int + frequency: + description: + - Gets or sets the frequency of the schedule. + default: one_time + type: str + choices: + - one_time + - day + - hour + - week + - month + - minute + time_zone: + description: + - Gets or sets the time zone of the schedule. + type: str + advanced_schedule: + description: + - Gets or sets the advanced schedule. + type: dict + suboptions: + week_days: + description: + - Days of the week that the job should execute on. + type: str + month_days: + description: + - Days of the month that the job should execute on. Must be between 1 and 31. + type: int + monthly_occurrences: + description: + - Occurrences of days within a month. + type: dict + suboptions: + occurrence: + description: + - Occurrence of the week within the month. Must be between 1 and 5. + type: int + day: + description: + - Day of the occurrence. Must be one of monday, tuesday, wednesday, thursday, friday, saturday, sunday. + default: monday + type: str + choices: + - monday + - tuesday + - wednesday + - thursday + - friday + - saturday + - sunday + creation_time: + description: + - Gets or sets the creation time. + type: str + last_modified_time: + description: + - Gets or sets the last modified time. + type: str + description: + description: + - Gets or sets the description. + type: str + tasks: + description: + - Tasks information for the Software update configuration. + type: dict + suboptions: + pre_task: + description: + - Pre task properties. + type: dict + suboptions: + parameters: + description: + - Gets or sets the parameters of the task. + type: dict + source: + description: + - Gets or sets the name of the runbook. + type: str + post_task: + description: + - Post task properties. + type: dict + suboptions: + parameters: + description: + - Gets or sets the parameters of the task. + type: dict + source: + description: + - Gets or sets the name of the runbook. + type: str + update_configuration: + description: + - update specific properties for the Software update configuration. + required: true + type: dict + suboptions: + operating_system: + description: + - operating system of target machines. + default: windows + type: str + choices: + - windows + - linux + windows: + description: + - Windows specific update configuration. + type: dict + suboptions: + included_update_classifications: + description: + - Update classification included in the software update configuration. A comma separated string with required values. + default: unclassified + type: str + choices: + - unclassified + - critical + - security + - update_rollup + - feature_pack + - service_pack + - definition + - tools + - updates + excluded_kb_numbers: + description: + - KB numbers excluded from the software update configuration. + type: str + included_kb_numbers: + description: + - KB numbers included from the software update configuration. + type: str + reboot_setting: + description: + - Reboot setting for the software update configuration. + type: str + linux: + description: + - Linux specific update configuration. + type: dict + suboptions: + included_package_classifications: + description: + - Update classifications included in the software update configuration. + default: unclassified + type: str + choices: + - unclassified + - critical + - security + - other + excluded_package_name_masks: + description: + - packages excluded from the software update configuration. + type: str + included_package_name_masks: + description: + - packages included from the software update configuration. + type: str + reboot_setting: + description: + - Reboot setting for the software update configuration. + type: str + duration: + description: + - Maximum time allowed for the software update configuration run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601. + type: str + azure_virtual_machines: + description: + - List of azure resource Ids for azure virtual machines targeted by the software update configuration. + - It can be the TBD name which is in the same resource group. + - "It can be the TBD ID. e.g., + /subscriptions/5ae68d89-69a4-454f-b5ce-e443cc4e0067/resourceGroups/myresources/providers/Microsoft.Compute/virtualMachines/vm-03." + - It can be a dict which contains C(name) and C(resource_group) of the TBD. + type: raw + non_azure_computer_names: + description: + - List of names of non-azure machines targeted by the software update configuration. + type: str + targets: + description: + - Group targets for the software update configuration. + type: dict + suboptions: + azure_queries: + description: + - List of Azure queries in the software update configuration. + type: dict + suboptions: + scope: + description: + - List of Subscription or Resource Group ARM Ids. + - It can be the TBD name which is in the same resource group. + - It can be the TBD ID. e.g., /subscriptions/5ae68d89-69a4-454f-b5ce-e443cc4e0067. + - It can be a dict which contains C(name) and C(resource_group) of the TBD. + type: raw + locations: + description: + - List of locations to scope the query to. + type: str + non_azure_queries: + description: + - List of non Azure queries in the software update configuration. + type: dict + suboptions: + function_alias: + description: + - Log Analytics Saved Search name. + type: str + workspace_id: + description: + - Workspace Id for Log Analytics in which the saved Search is resided. + type: str + state: + description: + - Assert the state of the Software Update Configuration. + - Use 'present' to create or update a Software Update Configuration and 'absent' to delete it. + default: present + choices: + - present + - absent + +extends_documentation_fragment: + - azure + +author: + - audevbot +''' + + +RETURN = ''' +provisioning_state: + description: + - Provisioning state for the software update configuration, which only appears in the response. + returned: always + type: str +creation_time: + description: + - Creation time of the resource, which only appears in the response. + returned: always + type: str +created_by: + description: + - CreatedBy property, which only appears in the response. + returned: always + type: str +last_modified_time: + description: + - Last time resource was modified, which only appears in the response. + returned: always + type: str +last_modified_by: + description: + - LastModifiedBy property, which only appears in the response. + returned: always + type: str +name: + description: + - Resource name. + returned: always + type: str +id: + description: + - Resource Id. + returned: always + type: str +type: + description: + - Resource type. + returned: always + type: str +''' + +import time +from ansible.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible.module_utils.common.dict_transformations import _snake_to_camel + +try: + from msrestazure.azure_exceptions import CloudError + from msrest.polling import LROPoller + from msrestazure.azure_operation import AzureOperationPoller + from msrest.serialization import Model + from azure.mgmt.automation import UpdateManagementAPIClient +except ImportError: + # This is handled in azure_rm_common + pass + + +class Actions: + NoAction, Create, Update, Delete = range(4) + + +class AzureRMSoftwareUpdateConfiguration(AzureRMModuleBaseExt): + """Configuration class for an Azure RM Software Update Configuration resource""" + + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + required=True, + type='str' + ), + name=dict( + required=True, + type='str' + ), + automation_account_name=dict( + required=True, + type='str', + updatable=False, + disposition='/' + ), + client_request_id=dict( + type='str', + updatable=False, + disposition='/' + ), + error=dict( + type='dict', + options=dict( + code=dict( + type='str' + ), + message=dict( + type='str' + ) + ) + ), + schedule_info=dict( + required=True, + type='dict', + options=dict( + start_time=dict( + type='str' + ), + expiry_time=dict( + type='str' + ), + expiry_time_offset_minutes=dict( + type='int' + ), + is_enabled=dict( + type='bool' + ), + next_run=dict( + type='str' + ), + next_run_offset_minutes=dict( + type='int' + ), + interval=dict( + type='int' + ), + frequency=dict( + default='one_time', + type='str', + choices=['one_time', 'day', 'hour', 'week', 'month', 'minute'] + ), + time_zone=dict( + type='str' + ), + advanced_schedule=dict( + type='dict', + options=dict( + week_days=dict( + type='str' + ), + month_days=dict( + type='int' + ), + monthly_occurrences=dict( + type='dict', + options=dict( + occurrence=dict( + type='int' + ), + day=dict( + default='monday', + type='str', + choices=['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] + ) + ) + ) + ) + ), + creation_time=dict( + type='str' + ), + last_modified_time=dict( + type='str' + ), + description=dict( + type='str' + ) + ) + ), + tasks=dict( + type='dict', + options=dict( + pre_task=dict( + type='dict', + options=dict( + parameters=dict( + type='dict' + ), + source=dict( + type='str' + ) + ) + ), + post_task=dict( + type='dict', + options=dict( + parameters=dict( + type='dict' + ), + source=dict( + type='str' + ) + ) + ) + ) + ), + update_configuration=dict( + required=True, + type='dict', + options=dict( + operating_system=dict( + default='windows', + type='str', + choices=['windows', 'linux'] + ), + windows=dict( + type='dict', + options=dict( + included_update_classifications=dict( + default='unclassified', + type='str', + choices=['unclassified', 'critical', 'security', 'update_rollup', 'feature_pack', 'service_pack', 'definition', 'tools', 'updates'] + ), + excluded_kb_numbers=dict( + type='str' + ), + included_kb_numbers=dict( + type='str' + ), + reboot_setting=dict( + type='str' + ) + ) + ), + linux=dict( + type='dict', + options=dict( + included_package_classifications=dict( + default='unclassified', + type='str', + choices=['unclassified', 'critical', 'security', 'other'] + ), + excluded_package_name_masks=dict( + type='str' + ), + included_package_name_masks=dict( + type='str' + ), + reboot_setting=dict( + type='str' + ) + ) + ), + duration=dict( + type='str' + ), + azure_virtual_machines=dict( + type='raw' + ), + non_azure_computer_names=dict( + type='str' + ), + targets=dict( + type='dict', + options=dict( + azure_queries=dict( + type='dict', + options=dict( + scope=dict( + type='raw' + ), + locations=dict( + type='str' + ) + ) + ), + non_azure_queries=dict( + type='dict', + options=dict( + function_alias=dict( + type='str' + ), + workspace_id=dict( + type='str' + ) + ) + ) + ) + ) + ) + ), + state=dict( + type='str', + default='present', + choices=['present', 'absent'] + ) + ) + + self.resource_group = None + self.automation_account_name = None + self.name = None + self.client_request_id = None + self.parameters = dict() + + self.results = dict(changed=False) + self.mgmt_client = None + self.state = None + self.to_do = Actions.NoAction + + super(AzureRMSoftwareUpdateConfiguration, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=False) + + def exec_module(self, **kwargs): + """Main module execution method""" + + for key in list(self.module_arg_spec.keys()): + if hasattr(self, key): + setattr(self, key, kwargs[key]) + elif kwargs[key] is not None: + self.parameters[key] = kwargs[key] + + if self.parameters.get('schedule_info') is not None: + self.parameters['schedule_info']['frequency'] = _snake_to_camel(self.parameters['schedule_info']['frequency'], True) + if self.parameters['schedule_info'].get('advanced_schedule') is not None: + if self.parameters['schedule_info']['advanced_schedule'].get('monthly_occurrences') is not None: + self.parameters['schedule_info']['advanced_schedule']['monthly_occurrences']['day'] = _snake_to_camel(self.parameters['schedule_info']['advanced_schedule']['monthly_occurrences']['day'], True) + if self.parameters.get('update_configuration') is not None: + self.parameters['update_configuration']['operating_system'] = _snake_to_camel(self.parameters['update_configuration']['operating_system'], True) + if self.parameters['update_configuration'].get('windows') is not None: + self.parameters['update_configuration']['windows']['included_update_classifications'] = _snake_to_camel(self.parameters['update_configuration']['windows']['included_update_classifications'], True) + if self.parameters['update_configuration'].get('linux') is not None: + self.parameters['update_configuration']['linux']['included_package_classifications'] = _snake_to_camel(self.parameters['update_configuration']['linux']['included_package_classifications'], True) + if self.parameters['update_configuration'].get('azure_virtual_machines') is not None: + self.parameters['update_configuration']['azure_virtual_machines'] = self.normalize_resource_id( + self.parameters['update_configuration']['azure_virtual_machines'], + '/subscriptions/5ae68d89-69a4-454f-b5ce-e443cc4e0067/resourceGroups/myresources/providers/Microsoft.Compute/virtualMachines/vm-03') + if self.parameters['update_configuration'].get('targets') is not None: + if self.parameters['update_configuration']['targets'].get('azure_queries') is not None: + if self.parameters['update_configuration']['targets']['azure_queries'].get('scope') is not None: + self.parameters['update_configuration']['targets']['azure_queries']['scope'] = self.normalize_resource_id( + self.parameters['update_configuration']['targets']['azure_queries']['scope'], + '/subscriptions/5ae68d89-69a4-454f-b5ce-e443cc4e0067') + + response = None + + self.mgmt_client = self.get_mgmt_svc_client(UpdateManagementAPIClient, + base_url=self._cloud_environment.endpoints.resource_manager) + + old_response = self.get_softwareupdateconfiguration() + + if not old_response: + self.log("Software Update Configuration instance doesn't exist") + if self.state == 'absent': + self.log("Old instance didn't exist") + else: + self.to_do = Actions.Create + else: + self.log("Software Update Configuration instance already exists") + if self.state == 'absent': + self.to_do = Actions.Delete + elif self.state == 'present': + self.results['old'] = old_response + self.results['new'] = self.parameters + if not self.idempotency_check(old_response, self.parameters): + self.to_do = Actions.Update + + if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): + self.log("Need to Create / Update the Software Update Configuration instance") + + self.results['changed'] = True + if self.check_mode: + return self.results + + response = self.create_update_softwareupdateconfiguration() + + self.log("Creation / Update done") + elif self.to_do == Actions.Delete: + self.log("Software Update Configuration instance deleted") + self.results['changed'] = True + + if self.check_mode: + return self.results + + self.delete_softwareupdateconfiguration() + else: + self.log("Software Update Configuration instance unchanged") + self.results['changed'] = False + response = old_response + + if self.state == 'present': + self.results.update({ + 'provisioning_state': response.get('provisioning_state', None), + 'creation_time': response.get('creation_time', None), + 'created_by': response.get('created_by', None), + 'last_modified_time': response.get('last_modified_time', None), + 'last_modified_by': response.get('last_modified_by', None), + 'name': response.get('name', None), + 'id': response.get('id', None), + 'type': response.get('type', None) + }) + return self.results + + def create_update_softwareupdateconfiguration(self): + ''' + Creates or updates Software Update Configuration with the specified configuration. + + :return: deserialized Software Update Configuration instance state dictionary + ''' + self.log("Creating / Updating the Software Update Configuration instance {0}".format(self.name)) + + try: + response = self.mgmt_client.software_update_configurations.create(resource_group_name=self.resource_group, + automation_account_name=self.automation_account_name, + software_update_configuration_name=self.name, + client_request_id=self.client_request_id, + parameters=self.parameters) + if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + response = self.get_poller_result(response) + except CloudError as exc: + self.log('Error attempting to create the Software Update Configuration instance.') + self.fail("Error creating the Software Update Configuration instance: {0}".format(str(exc))) + return response.as_dict() + + def delete_softwareupdateconfiguration(self): + ''' + Deletes specified Software Update Configuration instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Deleting the Software Update Configuration instance {0}".format(self.name)) + try: + response = self.mgmt_client.software_update_configurations.delete(resource_group_name=self.resource_group, + automation_account_name=self.automation_account_name, + software_update_configuration_name=self.name, + client_request_id=self.client_request_id) + except CloudError as e: + self.log('Error attempting to delete the Software Update Configuration instance.') + self.fail("Error deleting the Software Update Configuration instance: {0}".format(str(e))) + + if isinstance(response, LROPoller) or isinstance(response, AzureOperationPoller): + response = self.get_poller_result(response) + return True + + def get_softwareupdateconfiguration(self): + ''' + Gets the properties of the specified Software Update Configuration + :return: deserialized Software Update Configuration instance state dictionary + ''' + self.log("Checking if the Software Update Configuration instance {0} is present".format(self.name)) + found = False + try: + response = self.mgmt_client.software_update_configurations.get_by_name(resource_group_name=self.resource_group, + automation_account_name=self.automation_account_name, + software_update_configuration_name=self.name, + client_request_id=self.client_request_id) + found = True + self.log("Response : {0}".format(response)) + self.log("Software Update Configuration instance : {0} found".format(response.name)) + except CloudError as e: + self.log('Did not find the Software Update Configuration instance.') + if found is True: + return response.as_dict() + return False + + +def main(): + """Main execution""" + AzureRMSoftwareUpdateConfiguration() + + +if __name__ == '__main__': + main()