#!/usr/bin/python # # Copyright (c) 2018 Yuwei Zhou, # # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' --- module: azure_rm_servicebustopic version_added: "0.1.2" short_description: Manage Azure Service Bus description: - Create, update or delete an Azure Service Bus topics. options: resource_group: description: - Name of resource group. required: true type: str name: description: - Name of the topic. required: true type: str namespace: description: - Servicebus namespace name. - A namespace is a scoping container for all messaging components. - Multipletopics can reside within a single namespace. type: str required: true state: description: - Assert the state of the topic. Use C(present) to create or update and use C(absent) to delete. default: present type: str choices: - absent - present auto_delete_on_idle_in_seconds: description: - Time idle interval after which a topic is automatically deleted. - The minimum duration is 5 minutes. type: int default_message_time_to_live_seconds: description: - Default message timespan to live value. - This is the duration after which the message expires, starting from when the message is sent to Service Bus. - This is the default value used when TimeToLive is not set on a message itself. type: int enable_batched_operations: description: - Value that indicates whether server-side batched operations are enabled. type: bool enable_express: description: - Value that indicates whether Express Entities are enabled. - An express topic holds a message in memory temporarily before writing it to persistent storage. type: bool enable_partitioning: description: - A value that indicates whether the topic is to be partitioned across multiple message brokers. type: bool max_message_size_in_kb: description: - Maximum size (in KB) of the message payload that can be accepted by the queue. - This property is only used in Premium today and default is 1024. type: int max_size_in_mb: description: - The maximum size of the topic in megabytes, which is the size of memory allocated for the topic. type: int requires_duplicate_detection: description: - A value indicating if this topic requires duplicate detection. type: bool duplicate_detection_time_in_seconds: description: - TimeSpan structure that defines the duration of the duplicate detection history. type: int support_ordering: description: - Value that indicates whether the topic supports ordering. type: bool status: description: - Status of the entity. type: str choices: - active - disabled - send_disabled - receive_disabled extends_documentation_fragment: - azure.azcollection.azure author: - Yuwei Zhou (@yuwzho) ''' EXAMPLES = ''' - name: Create a topic azure_rm_servicebustopic: name: subtopic resource_group: myResourceGroup namespace: bar duplicate_detection_time_in_seconds: 600 ''' RETURN = ''' id: description: - Current state of the topic. returned: success type: str sample: "/subscriptions/xxx...xxx/resourceGroups/myResourceGroup/providers/Microsoft.ServiceBus/namespaces/nsb57dc95979/topics/topicb57dc95979" ''' try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase except ImportError: # This is handled in azure_rm_common pass from ansible.module_utils.common.dict_transformations import _snake_to_camel, _camel_to_snake from ansible.module_utils._text import to_native from datetime import datetime, timedelta duration_spec_map = dict( default_message_time_to_live='default_message_time_to_live_seconds', duplicate_detection_history_time_window='duplicate_detection_time_in_seconds', auto_delete_on_idle='auto_delete_on_idle_in_seconds' ) sas_policy_spec = dict( state=dict(type='str', default='present', choices=['present', 'absent']), name=dict(type='str', required=True), regenerate_key=dict(type='bool'), rights=dict(type='str', choices=['manage', 'listen', 'send', 'listen_send']) ) class AzureRMServiceBusTopic(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( auto_delete_on_idle_in_seconds=dict(type='int'), default_message_time_to_live_seconds=dict(type='int'), duplicate_detection_time_in_seconds=dict(type='int'), enable_batched_operations=dict(type='bool'), enable_express=dict(type='bool'), enable_partitioning=dict(type='bool'), max_size_in_mb=dict(type='int'), max_message_size_in_kb=dict(type='int'), name=dict(type='str', required=True), namespace=dict(type='str', required=True), requires_duplicate_detection=dict(type='bool'), resource_group=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), status=dict(type='str', choices=['active', 'disabled', 'send_disabled', 'receive_disabled']), support_ordering=dict(type='bool') ) self.resource_group = None self.name = None self.state = None self.namespace = None self.auto_delete_on_idle_in_seconds = None self.default_message_time_to_live_seconds = None self.enable_batched_operations = None self.enable_express = None self.enable_partitioning = None self.max_size_in_mb = None self.requires_duplicate_detection = None self.status = None self.support_ordering = None self.max_message_size_in_kb = None self.results = dict( changed=False, id=None ) super(AzureRMServiceBusTopic, self).__init__(self.module_arg_spec, supports_tags=False, supports_check_mode=True) def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) changed = False original = self.get() if self.state == 'present': # Create the resource instance params = dict( enable_batched_operations=self.enable_batched_operations, enable_express=self.enable_express, enable_partitioning=self.enable_partitioning, max_size_in_megabytes=self.max_size_in_mb, max_message_size_in_kilobytes=self.max_message_size_in_kb, support_ordering=self.support_ordering ) if self.status: params['status'] = self.servicebus_models.EntityStatus(str.capitalize(_snake_to_camel(self.status))) for k, v in duration_spec_map.items(): seconds = getattr(self, v) if seconds: params[k] = timedelta(seconds=seconds) instance = self.servicebus_models.SBTopic(**params) result = original if not original: changed = True result = instance else: result = original attribute_map = set(self.servicebus_models.SBTopic._attribute_map.keys()) - set(self.servicebus_models.SBTopic._validation.keys()) for attribute in attribute_map: value = getattr(instance, attribute) if value and value != getattr(original, attribute): changed = True if changed and not self.check_mode: result = self.create_or_update(instance) self.results = self.to_dict(result) elif original: changed = True if not self.check_mode: self.delete() self.results['deleted'] = True self.results['changed'] = changed return self.results def create_or_update(self, param): try: client = self._get_client() return client.create_or_update(self.resource_group, self.namespace, self.name, param) except Exception as exc: self.fail('Error creating or updating topic {0} - {1}'.format(self.name, str(exc.inner_exception) or str(exc))) def delete(self): try: client = self._get_client() client.delete(self.resource_group, self.namespace, self.name) return True except Exception as exc: self.fail("Error deleting topic {0} - {1}".format(self.name, str(exc))) def _get_client(self): return self.servicebus_client.topics def get(self): try: client = self._get_client() return client.get(self.resource_group, self.namespace, self.name) except Exception: return None def to_dict(self, instance): result = dict() attribute_map = self.servicebus_models.SBTopic._attribute_map for attribute in attribute_map.keys(): value = getattr(instance, attribute) if not value: continue if attribute_map[attribute]['type'] == 'duration': if is_valid_timedelta(value): key = duration_spec_map.get(attribute) or attribute result[key] = int(value.total_seconds()) elif attribute == 'status': result['status'] = _camel_to_snake(value) elif isinstance(value, self.servicebus_models.MessageCountDetails): result[attribute] = value.as_dict() elif isinstance(value, self.servicebus_models.SBSku): result[attribute] = value.name.lower() elif isinstance(value, datetime): result[attribute] = str(value) elif isinstance(value, str): result[attribute] = to_native(value) elif attribute == 'max_size_in_megabytes': result['max_size_in_mb'] = value elif attribute == 'max_message_size_in_kilobyte': result['max_message_size_in_kb'] = value else: result[attribute] = value return result def is_valid_timedelta(value): if value == timedelta(10675199, 10085, 477581): return None return value def main(): AzureRMServiceBusTopic() if __name__ == '__main__': main()