class SolaceGetServiceAuthenticationLdapProfilesTask(SolaceGetTask): def __init__(self, module): super().__init__(module) self.config = SolaceTaskBrokerConfig(module) self.sempv1_get_paging_api = SolaceSempV1PagingGetApi(module) self.solace_cloud_api = SolaceCloudApi(module) def get_config(self) -> SolaceTaskBrokerConfig: return self.config def _get_list_solace_cloud(self): # GET services/{service-id}/requests/ldapAuthenticationProfile/default # only 1 exists, name=default service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, 'ldapAuthenticationProfile', 'default'] return [self.solace_cloud_api.get_object_settings(self.get_config(), path_array)] def get_list(self): if self.get_config().is_solace_cloud(): return self._get_list_solace_cloud() # SEMP V1 params = self.get_config().get_params() rpc_dict = { 'show': { 'ldap-profile': { 'profile-name': params['where_name'] } } } # test: paging # 'count': '', # 'num-elements': 1 response_list_path_array = [ 'rpc-reply', 'rpc', 'show', 'ldap-profile', 'ldap-profile'] return self.sempv1_get_paging_api.get_objects(self.get_config(), self.sempv1_get_paging_api.convertDict2Sempv1RpcXmlString(rpc_dict), response_list_path_array) def do_task(self): objects = self.get_list() result = self.create_result_with_list(objects) return None, result
def __init__(self, module): super().__init__(module) self.config = SolaceTaskBrokerConfig(module) self.sempv1_get_paging_api = SolaceSempV1PagingGetApi(module) self.solace_cloud_api = SolaceCloudApi(module)
def __init__(self, module): super().__init__(module) self.solace_cloud_api = SolaceCloudApi(module)
def __init__(self, module: AnsibleModule): super().__init__(module) self.config = SolaceTaskSolaceCloudConfig(module) self.solace_cloud_api = SolaceCloudApi(module)
class SolaceCloudServiceTask(SolaceCloudCRUDTask): KEY_SERVICE_ID = 'serviceId' KEY_NAME = 'name' def __init__(self, module): super().__init__(module) self.solace_cloud_api = SolaceCloudApi(module) def validate_params(self): # state=present: name is required # state=absent: name or service_id required params = self.get_module().params name = params.get('name', None) service_id = params.get(self.get_config().PARAM_SERVICE_ID, None) state = params['state'] if state == 'present' and not name: raise SolaceParamsValidationError( 'name', name, "required for state='present'") if state == 'absent' and not name and not service_id: raise SolaceParamsValidationError( f"name, {self.get_config().PARAM_SERVICE_ID}", name, "at least one is required for state='absent'") def get_args(self): params = self.get_module().params service_id = params.get(self.get_config().PARAM_SERVICE_ID, None) if service_id: return self.KEY_SERVICE_ID, service_id name = params['name'] return [self.KEY_NAME, name] def get_func(self, key, value): if key == self.KEY_NAME: services = self.solace_cloud_api.get_services(self.get_config()) service = self.solace_cloud_api.find_service_by_name_in_services( services, value) if not service: return None service_id = service[self.KEY_SERVICE_ID] else: service_id = value # save service_id self._service_id = service_id service = self.solace_cloud_api.get_service( self.get_config(), self._service_id) if not service: return None if service['creationState'] == 'failed': logging.debug( "solace cloud service '%s' in failed state - deleting ...", value) _resp = self.solace_cloud_api.delete_service( self.get_config(), self._service_id) return None wait_timeout_minutes = self.get_module().params['wait_timeout_minutes'] if service['creationState'] != 'completed' and wait_timeout_minutes > 0: logging.debug( "solace cloud service creationState not completed (creationState=%s) - waiting to complete ...", service['creationState']) service = self.solace_cloud_api.wait_for_service_create_completion( self.get_config(), wait_timeout_minutes, self._service_id) return service def create_func(self, key, name, settings=None): if not settings: raise SolaceParamsValidationError( 'settings', settings, "required for creating a service") data = { 'adminState': 'start', 'partitionId': 'default', 'name': name } data.update(settings) return self.solace_cloud_api.create_service(self.get_config(), self.get_module().params['wait_timeout_minutes'], data) # TODO: wait until implemented in Solace Cloud API # def update_func(self, key, name, settings=None, delta_settings=None): # if not settings: # raise SolaceParamsValidationError('settings', settings, "required for creating a service") # data = { # 'adminState': 'start', # 'partitionId': 'default', # 'name': name # } # data.update(settings) # return self.solace_cloud_api.create_service(self.get_config(), self.get_module().params['wait_timeout_minutes'], data) def update_func(self, key, value, settings=None, delta_settings=None): msg = [ f"Solace Cloud Service '{key}={value}' already exists.", "You cannot update an existing service. Only option: delete & re-create.", "changes requested: see 'delta'" ] raise SolaceError(msg, dict(delta=delta_settings)) def delete_func(self, key, value): return self.solace_cloud_api.delete_service(self.get_config(), self._service_id)
class SolaceCloudClientProfileTask(SolaceBrokerCRUDTask): OBJECT_KEY = 'clientProfileName' OPERATION = 'clientProfile' CREATE_DEFAULTS = { "allowGuaranteedMsgSendEnabled": "true", "allowGuaranteedMsgReceiveEnabled": "true", "allowUseCompression": "true", "replicationAllowClientConnectWhenStandbyEnabled": "false", "allowTransactedSessionsEnabled": "true", "allowBridgeConnectionsEnabled": "true", "allowGuaranteedEndpointCreateEnabled": "true", "allowSharedSubscriptionsEnabled": True, "apiQueueManagementCopyFromOnCreateName": "", "apiTopicEndpointManagementCopyFromOnCreateName": "", "serviceWebInactiveTimeout": "30", "serviceWebMaxPayload": "1000000", "maxConnectionCountPerClientUsername": "******", "serviceSmfMaxConnectionCountPerClientUsername": "******", "serviceWebMaxConnectionCountPerClientUsername": "******", "maxEndpointCountPerClientUsername": "******", "maxEgressFlowCount": "100", "maxIngressFlowCount": "100", "maxSubscriptionCount": "1000", "maxTransactedSessionCount": "100", "maxTransactionCount": "500", "queueGuaranteed1MaxDepth": "20000", "queueGuaranteed1MinMsgBurst": 66000, "queueDirect1MaxDepth": "20000", "queueDirect1MinMsgBurst": "4", "queueDirect2MaxDepth": "20000", "queueDirect2MinMsgBurst": "4", "queueDirect3MaxDepth": "20000", "queueDirect3MinMsgBurst": "4", "queueControl1MaxDepth": "20000", "queueControl1MinMsgBurst": "4", "tcpCongestionWindowSize": "2", "tcpKeepaliveCount": "5", "tcpKeepaliveIdleTime": "3", "tcpKeepaliveInterval": "1", "tcpMaxSegmentSize": "1460", "tcpMaxWindowSize": "256", "elidingDelay": 0, "elidingEnabled": True, "elidingMaxTopicCount": 256, "rejectMsgToSenderOnNoSubscriptionMatchEnabled": False, "tlsAllowDowngradeToPlainTextEnabled": True, "eventClientProvisionedEndpointSpoolUsageThreshold": { "setPercent": "80", "clearPercent": "60" } } def __init__(self, module): super().__init__(module) self.solace_cloud_api = SolaceCloudApi(module) def _adjust_settings_for_create(self, new_settings) -> dict: # placeholder in case customized data type transformation required for create operation return new_settings if new_settings else {} def _adjust_settings_for_update(self, new_settings, get_settings) -> dict: # add mandatory if 'eventClientProvisionedEndpointSpoolUsageThreshold' not in new_settings: new_settings[ 'eventClientProvisionedEndpointSpoolUsageThreshold'] = get_settings[ 'eventClientProvisionedEndpointSpoolUsageThreshold'] return new_settings def get_settings_type_conversion(self, d): # everything is a string or null # import logging # import json # logging.debug(f"d={json.dumps(d, indent=2)}") for k, i in d.items(): t = type(i) if t == dict: d[k] = self.get_settings_type_conversion(i) else: if i and t != str: raise SolaceInternalError( f"unhandled type, field={k}, value={i}, type={t}") if not i: # placeholder, leave it for now d[k] = None elif i == "": # placeholder, leave it for now d[k] = i elif i.lower() == 'false': d[k] = False elif i.lower() == 'true': d[k] = True elif re.search(r'^[0-9]+$', i): d[k] = int(i) elif re.search(r'^[0-9]+\.[0-9]$', i): d[k] = float(i) else: # leave any other strings d[k] = i return d def normalize_current_settings(self, current_settings: dict, new_settings: dict) -> dict: normalized_current_settings = self.get_settings_type_conversion( current_settings) if current_settings else None return normalized_current_settings def normalize_new_settings(self, new_settings) -> dict: if new_settings: SolaceUtils.type_conversion(new_settings, False) return new_settings def get_args(self): params = self.get_module().params return [params['name']] def get_settings_arg_name(self) -> str: return 'solace_cloud_settings' def _compose_request_body(self, operation: str, operation_type: str, settings: dict) -> dict: return {'operation': operation, operation_type: settings} def get_func(self, client_profile_name): # GET services/{paste-your-serviceId-here}/clientProfiles/{{clientProfileName}} service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, 'clientProfiles', client_profile_name ] return self.solace_cloud_api.get_object_settings( self.get_config(), path_array) def create_func(self, client_profile_name, settings=None): # POST services/{paste-your-serviceId-here}/requests/clientProfileRequests module_op = SolaceTaskOps.OP_CREATE_OBJECT data = {self.OBJECT_KEY: client_profile_name} data.update(self.CREATE_DEFAULTS) create_settings = self._adjust_settings_for_create(settings) data.update(create_settings) body = self._compose_request_body(operation='create', operation_type=self.OPERATION, settings=data) service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, SolaceCloudApi.API_REQUESTS, 'clientProfileRequests' ] return self.solace_cloud_api.make_service_post_request( self.get_config(), path_array, service_id, json_body=body, module_op=module_op) def update_func(self, client_profile_name, settings=None, delta_settings=None): module_op = SolaceTaskOps.OP_UPDATE_OBJECT # POST services/{paste-your-serviceId-here}/requests/clientProfileRequests get_settings = self.get_func(client_profile_name) update_settings = self._adjust_settings_for_update( delta_settings, get_settings) mandatory = {self.OBJECT_KEY: client_profile_name} data = mandatory data.update(update_settings) body = self._compose_request_body(operation='update', operation_type=self.OPERATION, settings=data) service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, SolaceCloudApi.API_REQUESTS, 'clientProfileRequests' ] return self.solace_cloud_api.make_service_post_request( self.get_config(), path_array, service_id, json_body=body, module_op=module_op) def delete_func(self, client_profile_name): module_op = SolaceTaskOps.OP_DELETE_OBJECT # POST services/{paste-your-serviceId-here}/requests/clientProfileRequests data = {self.OBJECT_KEY: client_profile_name} body = self._compose_request_body(operation='delete', operation_type=self.OPERATION, settings=data) service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, SolaceCloudApi.API_REQUESTS, 'clientProfileRequests' ] return self.solace_cloud_api.make_service_post_request( self.get_config(), path_array, service_id, json_body=body, module_op=module_op)
def __init__(self, module): super().__init__(module) self.sempv1_api = SolaceSempV1Api(module) self.solace_cloud_api = SolaceCloudApi(module) self.current_settings = None
class SolaceServiceAuthenticationLdapProfileTask(SolaceBrokerCRUDTask): MIN_SEMP_V1_VERSION = "9.1" def __init__(self, module): super().__init__(module) self.sempv1_api = SolaceSempV1Api(module) self.solace_cloud_api = SolaceCloudApi(module) self.current_settings = None def check_min_sempv1_supported_version(self): min_sempv1_version = SolaceUtils.create_version( self.MIN_SEMP_V1_VERSION) raw_api_version, version = self.sempv1_api.get_sempv1_version( self.get_config()) if version < min_sempv1_version: raise SolaceSempv1VersionNotSupportedError( self.get_module()._name, f"{version}({raw_api_version})", min_sempv1_version) def normalize_current_settings(self, current_settings: dict, new_settings: dict) -> dict: if self.get_config().is_solace_cloud(): # remember current_settings for update call: it needs it self.current_settings = current_settings return current_settings # SEMP V1 # TODO: implement to test if changes are requested. # not trivial, what is the schema? # convert current_settings to same data structure as new_settings return current_settings def do_task_extension(self, args, new_state, new_settings, current_settings): if not current_settings: name = self.get_module().params['name'] usr_msg = f"ldap profile '{name}' does not exist; cannot enable/disable" raise SolaceModuleUsageError(self.get_module()._name, new_state, usr_msg) if self.get_config().is_solace_cloud(): is_enabled = current_settings['enabled'] else: is_enabled = True if current_settings['shutdown'] == 'No' else False if new_state == 'enabled': if is_enabled: return None, self.create_result(rc=0, changed=False) result = self.create_result(rc=0, changed=True) if not self.get_module().check_mode: result['response'] = self.enable_func(*args) return None, result if new_state == 'disabled': if not is_enabled: return None, self.create_result(rc=0, changed=False) result = self.create_result(rc=0, changed=True) if not self.get_module().check_mode: result['response'] = self.disable_func(*args) return None, result super().do_task_extension(args, new_state, new_settings, current_settings) def validate_params(self): params = self.get_module().params name = params.get('name', None) if self.get_config().is_solace_cloud() and name != 'default': raise SolaceParamsValidationError( 'name', name, "ldap profile name for Solace Cloud must be 'default'.") invalid_chars = '-' if SolaceUtils.stringContainsAnyChars(name, invalid_chars): raise SolaceParamsValidationError( 'name', name, f"contains 1 or more invalid chars from set: '{invalid_chars}'" ) def get_args(self): params = self.get_module().params return [params['name']] def get_settings_arg_name(self) -> str: if self.get_config().is_solace_cloud(): return 'solace_cloud_settings' else: return 'sempv1_settings' def _get_func_solace_cloud(self, ldap_profile_name): # GET services/{service-id}/requests/ldapAuthenticationProfile/default service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, 'ldapAuthenticationProfile', ldap_profile_name ] return self.solace_cloud_api.get_object_settings( self.get_config(), path_array) def get_func(self, ldap_profile_name): if self.get_config().is_solace_cloud(): return self._get_func_solace_cloud(ldap_profile_name) # SEMP V1 self.check_min_sempv1_supported_version() rpc_dict = { 'show': { 'ldap-profile': { 'profile-name': ldap_profile_name, 'detail': None } } } _resp = self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(rpc_dict), SolaceTaskOps.OP_READ_OBJECT) _resp_ldap_profile = _resp['rpc-reply']['rpc']['show']['ldap-profile'] if _resp_ldap_profile: return _resp_ldap_profile['ldap-profile'] else: return None def _disable_func_solace_cloud(self, ldap_profile_name): data = {'enabled': False} return self._make_solace_cloud_update_request(ldap_profile_name, data) def disable_func(self, ldap_profile_name): if self.get_config().is_solace_cloud(): return self._disable_func_solace_cloud(ldap_profile_name) # SEMP V1 rpc_dict = { 'authentication': { 'ldap-profile': { 'profile-name': ldap_profile_name, 'shutdown': None } } } _resp = self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(rpc_dict), SolaceTaskOps.OP_UPDATE_OBJECT) _call_log = { self.sempv1_api.getNextCallKey(): { 'enable': { 'rpc': rpc_dict, 'response': _resp } } } return _call_log def _enable_func_solace_cloud(self, ldap_profile_name): data = {'enabled': True} return self._make_solace_cloud_update_request(ldap_profile_name, data) def enable_func(self, ldap_profile_name): if self.get_config().is_solace_cloud(): return self._enable_func_solace_cloud(ldap_profile_name) # SEMP V1 rpc_dict = { 'authentication': { 'ldap-profile': { 'profile-name': ldap_profile_name, 'no': { 'shutdown': None } } } } _resp = self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(rpc_dict), SolaceTaskOps.OP_UPDATE_OBJECT) _call_log = { self.sempv1_api.getNextCallKey(): { 'enable': { 'rpc': rpc_dict, 'response': _resp } } } return _call_log def _compose_solace_cloud_request_body(self, operation: str, settings: dict) -> dict: return {'operation': operation, 'ldapAuthenticationProfile': settings} def _make_solace_cloud_update_request(self, ldap_profile_name, settings): module_op = SolaceTaskOps.OP_UPDATE_OBJECT # POST services/{service-id}/requests/ldapAuthenticationProfileRequests data = self.current_settings if self.current_settings else {} data.update(settings if settings else {}) body = self._compose_solace_cloud_request_body(operation='update', settings=data) service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, SolaceCloudApi.API_REQUESTS, 'ldapAuthenticationProfileRequests' ] return self.solace_cloud_api.make_service_post_request( self.get_config(), path_array, service_id, json_body=body, module_op=module_op) def _create_func_solace_cloud(self, ldap_profile_name, settings): data = { 'profileName': ldap_profile_name, "searchDeref": "ALWAYS", "searchFilter": "(cn=$CLIENT_USERNAME)", "searchScope": "SUBTREE", "searchTimeout": 5, "groupMembershipSecondarySearchDeref": "ALWAYS", "groupMembershipSecondarySearchFilter": "(member=$ATTRIBUTE_VALUE_FROM_PRIMARY_SEARCH)", "groupMembershipSecondarySearchScope": "SUBTREE", "groupMembershipSecondarySearchTimeout": 5 } data.update(settings if settings else {}) return self._make_solace_cloud_update_request(ldap_profile_name, data) def create_func(self, ldap_profile_name, settings=None): if self.get_config().is_solace_cloud(): return self._create_func_solace_cloud(ldap_profile_name, settings) # SEMP V1 create_rpc_dict = { 'authentication': { 'create': { 'ldap-profile': { 'profile-name': ldap_profile_name } } } } resp = self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(create_rpc_dict), SolaceTaskOps.OP_CREATE_OBJECT) if settings: resp = self._update_func_sempv1(ldap_profile_name, settings, settings, SolaceTaskOps.OP_CREATE_OBJECT) return resp def _update_func_solace_cloud(self, ldap_profile_name, settings, delta_settings): return self._make_solace_cloud_update_request(ldap_profile_name, settings) def _send_sempv1_update(self, ldap_profile_name, key, val, op): _rpc_update_dict = {'authentication': {'ldap-profile': {key: val}}} _rpc_dict = { 'authentication': { 'ldap-profile': { 'profile-name': ldap_profile_name } } } rpc_dict = SolaceUtils.merge_dicts_recursive(_rpc_dict, _rpc_update_dict) return self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(rpc_dict), op) def _update_func_sempv1(self, ldap_profile_name, settings, delta_settings, op): if not settings: return None combined_resps = {} # iterate over settings.keys and send 1 update after the other for key, val in settings.items(): if val: if key == 'search' and isinstance(val, dict): # iterate through sarch for skey, sval in val.items(): _resp = self._send_sempv1_update( ldap_profile_name, key, {skey: sval}, op) _call_log = { self.sempv1_api.getNextCallKey(): { key: { skey: sval, 'response': _resp } } } combined_resps = SolaceUtils.merge_dicts_recursive( combined_resps, _call_log) else: _resp = self._send_sempv1_update(ldap_profile_name, key, val, op) _call_log = { self.sempv1_api.getNextCallKey(): { key: val, 'response': _resp } } combined_resps = SolaceUtils.merge_dicts_recursive( combined_resps, _call_log) return combined_resps def update_func(self, ldap_profile_name, settings=None, delta_settings=None): if self.get_config().is_solace_cloud(): return self._update_func_solace_cloud(ldap_profile_name, settings, delta_settings) return self._update_func_sempv1(ldap_profile_name, settings, delta_settings, SolaceTaskOps.OP_UPDATE_OBJECT) def _delete_func_solace_cloud(self, ldap_profile_name): raise SolaceNoModuleStateSupportError( self.get_module()._name, self.get_module().params['state'], 'Solace Cloud', 'disable profile instead') def delete_func(self, ldap_profile_name): if self.get_config().is_solace_cloud(): return self._delete_func_solace_cloud(ldap_profile_name) # SEMP V1 rpc_dict = { 'authentication': { 'no': { 'ldap-profile': { 'profile-name': ldap_profile_name } } } } return self.sempv1_api.make_post_request( self.get_config(), self.sempv1_api.convertDict2Sempv1RpcXmlString(rpc_dict), SolaceTaskOps.OP_DELETE_OBJECT)
def __init__(self, module): super().__init__(module) self.sempv2_api = SolaceSempV2Api(module) self.sempv1_api = SolaceSempV1Api(module) self.solace_cloud_api = SolaceCloudApi(module)
class SolaceGatherFactsTask(SolaceBrokerGetTask): def __init__(self, module): super().__init__(module) self.sempv2_api = SolaceSempV2Api(module) self.sempv1_api = SolaceSempV1Api(module) self.solace_cloud_api = SolaceCloudApi(module) def add_path_value(self, dictionary, path_array, value): if len(path_array) > 1: if path_array[0] not in dictionary.keys(): dictionary[path_array[0]] = {} self.add_path_value(dictionary[path_array[0]], path_array[1:], value) else: if (path_array[0] == ''): dictionary['broker'] = value else: dictionary[path_array[0]] = value def get_about_info(self): # GET /about, /about/api, /about/user, /about/user/msgVpns about_info = {} path_array_list = [["about"], ["about", "user"], ["about", "user", "msgVpns"], ["about", "api"]] for path_array in path_array_list: resp = self.sempv2_api.make_get_request( self.get_config(), [SolaceSempV2Api.API_BASE_SEMPV2_CONFIG] + path_array) self.add_path_value(about_info, path_array, resp) about_info['isSolaceCloud'] = self.get_config().is_solace_cloud() return about_info def get_service_info(self) -> dict: use_sempv1_also = self.get_config().get_params()['use_sempv1_also'] resp = dict(vpns={}) # get service info if self.get_config().is_solace_cloud(): resp['solace_cloud_service'] = self.solace_cloud_api.get_service( self.get_config(), self.get_module().params['solace_cloud_service_id']) resp['virtualRouterName'] = "n/a" else: path_array = [SolaceSempV2Api.API_BASE_SEMPV2_CONFIG] resp['sempv2_service'] = self.sempv2_api.get_object_settings( self.get_config(), path_array) if use_sempv1_also: # get virtual router xml_post_cmd = "<rpc><show><router-name></router-name></show></rpc>" resp_virtual_router = self.sempv1_api.make_post_request( self.get_config(), xml_post_cmd, SolaceTaskOps.OP_READ_OBJECT) resp['virtualRouterName'] = resp_virtual_router['rpc-reply'][ 'rpc']['show']['router-name']['router-name'] # get vpns info msg_vpns = self.sempv2_api.make_get_request(self.get_config(), [ SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, "about", "user", "msgVpns" ]) for msg_vpn in msg_vpns: # GET /msgVpns/{msgVpnName} vpn_name = msg_vpn['msgVpnName'] path_array = [ SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, 'msgVpns', vpn_name ] msg_vpn_info = self.sempv2_api.get_object_settings( self.get_config(), path_array) resp['vpns'].update({vpn_name: msg_vpn_info}) return resp def do_task(self): ansible_facts = dict(solace={}) about_info = self.get_about_info() service_info = self.get_service_info() ansible_facts['solace'].update(about_info) ansible_facts['solace'].update(service_info) result = self.create_result() result.update(dict(ansible_facts=ansible_facts)) return None, result
class SolaceVpnTask(SolaceBrokerCRUDTask): OBJECT_KEY = 'msgVpnName' SOLACE_CLOUD_SETTINGS = { 'authenticationBasicEnabled': False, 'authenticationBasicType': ['LDAP', 'INTERNAL', 'NONE'], 'authenticationClientCertEnabled': False, 'authenticationClientCertValidateDateEnabled': False, 'authenticationOauthEnabled': False, 'authenticationClientCertAllowApiProvidedUsernameEnabled': False, 'authenticationClientCertUsernameSource': ['COMMON_NAME', 'SUBJECT_ALTERNATE_NAME_MSUPN'] } def __init__(self, module): super().__init__(module) self.sempv2_api = SolaceSempV2Api(module) self.solace_cloud_api = SolaceCloudApi(module) self.current_settings = None def validate_params(self): pass def get_args(self): params = self.get_module().params return [params['name']] def get_settings_arg_name(self) -> str: return 'sempv2_settings' def normalize_current_settings(self, current_settings: dict, new_settings: dict) -> dict: if self.get_config().is_solace_cloud(): # remember current_settings for update call: it needs it self.current_settings = current_settings return current_settings def _remove_solace_cloud_keys(self, settings): _settings = SolaceUtils.deep_copy(settings) for key in self.SOLACE_CLOUD_SETTINGS.keys(): _settings.pop(key, None) return _settings def _convert_new_settings_to_solace_cloud_api(self, new_settings): val = new_settings.get('authenticationBasicType', None) if val: new_val = val.upper().replace('-', '_') new_settings['authenticationBasicType'] = new_val val = new_settings.get('authenticationClientCertUsernameSource', None) if val: new_val = val.upper().replace('-', '_') new_settings['authenticationClientCertUsernameSource'] = new_val return new_settings def _normalize_new_settings_solace_cloud(self, new_settings): val = new_settings.get('authenticationBasicType', None) if val: new_val = val.lower().replace('_', '-') new_settings['authenticationBasicType'] = new_val val = new_settings.get('authenticationClientCertUsernameSource', None) if val: new_val = val.lower().replace('_', '-') new_settings['authenticationClientCertUsernameSource'] = new_val return new_settings def normalize_new_settings(self, new_settings) -> dict: # solace cloud and self-hosted broker return the same types if new_settings: SolaceUtils.type_conversion(new_settings, False) if self.get_config().is_solace_cloud(): new_settings = self._normalize_new_settings_solace_cloud( new_settings) return new_settings def get_func(self, vpn_name): # notes: # - solace-cloud: could get the settings via: GET the service: msgVpnAttributes. but looks like they are the same # GET /msgVpns/{msgVpnName} path_array = [ SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, 'msgVpns', vpn_name ] return self.sempv2_api.get_object_settings(self.get_config(), path_array) def create_func(self, vpn_name, settings=None): if self.get_config().is_solace_cloud(): raise SolaceModuleUsageError( self.get_module()._name, self.get_module().params['state'], "cannot create a new message vpn on a Solace Cloud service") # POST /msgVpns data = {self.OBJECT_KEY: vpn_name} data.update(settings if settings else {}) path_array = [SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, 'msgVpns'] return self.sempv2_api.make_post_request(self.get_config(), path_array, data) def _update_func_solace_cloud(self, vpn_name, settings, delta_settings): # extract solace cloud api settings from settings -> send via solace cloud api # rest: send via sempv2 api _solace_cloud_api_settings = {} for key in self.SOLACE_CLOUD_SETTINGS.keys(): _solace_cloud_api_settings.update({ key: settings[key] if key in settings else self.current_settings[key] }) _solace_cloud_api_settings = self._convert_new_settings_to_solace_cloud_api( _solace_cloud_api_settings) # POST: services/{service-id}}/requests/updateAuthenticationRequests module_op = SolaceTaskOps.OP_UPDATE_OBJECT service_id = self.get_config().get_params()['solace_cloud_service_id'] path_array = [ SolaceCloudApi.API_BASE_PATH, SolaceCloudApi.API_SERVICES, service_id, SolaceCloudApi.API_REQUESTS, 'updateAuthenticationRequests' ] solace_cloud_resp = self.solace_cloud_api.make_service_post_request( self.get_config(), path_array, service_id, json_body=_solace_cloud_api_settings, module_op=module_op) # check for sempv2 settings, extract and send _sempv2_api_settings = self._remove_solace_cloud_keys(settings) sempv2_resp = {} if _sempv2_api_settings: sempv2_resp = self._update_func_sempv2(vpn_name, _sempv2_api_settings) resp = {'solace-cloud': solace_cloud_resp, 'semp-v2': sempv2_resp} return resp def _update_func_sempv2(self, vpn_name, settings=None, delta_settings=None): # PATCH /msgVpns/{msgVpnName} path_array = [ SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, 'msgVpns', vpn_name ] return self.sempv2_api.make_patch_request(self.get_config(), path_array, settings) def update_func(self, vpn_name, settings=None, delta_settings=None): if self.get_config().is_solace_cloud(): return self._update_func_solace_cloud(vpn_name, settings, delta_settings) return self._update_func_sempv2(vpn_name, settings, delta_settings) def delete_func(self, vpn_name): if self.get_config().is_solace_cloud(): raise SolaceModuleUsageError( self.get_module()._name, self.get_module().params['state'], "cannot delete a message vpn on a Solace Cloud service") # DELETE /msgVpns/{msgVpnName} path_array = [ SolaceSempV2Api.API_BASE_SEMPV2_CONFIG, 'msgVpns', vpn_name ] return self.sempv2_api.make_delete_request(self.get_config(), path_array)