def add_member(module, check_mode, api, tenant, tenant_uuid, existing_obj, data, name, api_version): rsp = None if not existing_obj: # create the object changed = True if check_mode: rsp = AviCheckModeResponse(obj=None) else: # creates group with single member req = {'name': name, 'groups': [data['group']] } # added api version for AVI api call. rsp = api.post('gslbservice', data=req, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) else: # found GSLB object req = deepcopy(existing_obj) if 'groups' not in req: req['groups'] = [] groups = [group for group in req['groups'] if group['name'] == data['group']['name']] if not groups: # did not find the group req['groups'].append(data['group']) else: # just update the existing group with members group = groups[0] group_info_wo_members = deepcopy(data['group']) group_info_wo_members.pop('members', None) group.update(group_info_wo_members) if 'members' not in group: group['members'] = [] new_members = [] for patch_member in data['group'].get('members', []): found = False for m in group['members']: if 'fqdn' in patch_member and m.get('fqdn', '') == patch_member['fqdn']: found = True break elif m['ip']['addr'] == patch_member['ip']['addr']: found = True break if not found: new_members.append(patch_member) else: m.update(patch_member) # add any new members group['members'].extend(new_members) cleanup_absent_fields(req) changed = not avi_obj_cmp(req, existing_obj) if changed and not check_mode: obj_path = '%s/%s' % ('gslbservice', existing_obj['uuid']) # added api version for AVI api call. rsp = api.put(obj_path, data=req, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) return changed, rsp
def add_member(module, check_mode, api, tenant, tenant_uuid, existing_obj, data, name, api_version): rsp = None if not existing_obj: # create the object changed = True if check_mode: rsp = AviCheckModeResponse(obj=None) else: # creates group with single member req = {'name': name, 'groups': [data['group']] } # added api version for AVI api call. rsp = api.post('gslbservice', data=req, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) else: # found GSLB object req = deepcopy(existing_obj) if 'groups' not in req: req['groups'] = [] groups = [group for group in req['groups'] if group['name'] == data['group']['name']] if not groups: # did not find the group req['groups'].append(data['group']) else: # just update the existing group with members group = groups[0] group_info_wo_members = deepcopy(data['group']) group_info_wo_members.pop('members', None) group.update(group_info_wo_members) if 'members' not in group: group['members'] = [] new_members = [] for patch_member in data['group'].get('members', []): found = False for m in group['members']: if 'fqdn' in patch_member and m.get('fqdn', '') == patch_member['fqdn']: found = True break elif m['ip']['addr'] == patch_member['ip']['addr']: found = True break if not found: new_members.append(patch_member) else: m.update(patch_member) # add any new members group['members'].extend(new_members) cleanup_absent_fields(req) changed = not avi_obj_cmp(req, existing_obj) if changed and not check_mode: obj_path = '%s/%s' % ('gslbservice', existing_obj['uuid']) # added api version for AVI api call. rsp = api.put(obj_path, data=req, tenant=tenant, tenant_uuid=tenant_uuid, api_version=api_version) return changed, rsp
def testCleanupFields(self): obj = {'name': 'testpool', 'scalar_field': {'state': 'absent'}, 'list_fields': [{'x': '1'}, {'y': {'state': 'absent'}}]} cleanup_absent_fields(obj) assert 'scalar_field' not in obj for elem in obj['list_fields']: print elem assert 'y' not in elem
def testCleanupFields(self): obj = {'name': 'testpool', 'scalar_field': {'state': 'absent'}, 'list_fields': [{'x': '1'}, {'y': {'state': 'absent'}}]} cleanup_absent_fields(obj) assert 'scalar_field' not in obj for elem in obj['list_fields']: print elem assert 'y' not in elem
def test_cleanup_abset(self): obj = { 'x': 10, 'y': { 'state': 'absent' }, 'z': { 'a': { 'state': 'absent' } } } cleanup_absent_fields(obj) assert 'y' not in obj assert 'a' not in obj['z']
def test_cleanup_abset(self): obj = { 'x': 10, 'y': { 'state': 'absent' }, 'z': { 'a': { 'state': 'absent' } }, 'l': [{ 'y1': { 'state': 'absent' } }], 'z1': { 'a': { 'state': 'absent' }, 'b': {}, 'c': 42 }, 'empty': [] } obj = cleanup_absent_fields(obj) assert 'y' not in obj assert 'z' not in obj assert 'l' not in obj assert 'z1' in obj assert 'b' not in obj['z1'] assert 'a' not in obj['z1'] assert 'empty' not in obj
def test_cleanup_abset(self): obj = {'x': 10, 'y': {'state': 'absent'}, 'z': {'a': {'state': 'absent'}}, 'l': [{'y1': {'state': 'absent'}}], 'z1': {'a': {'state': 'absent'}, 'b': {}, 'c': 42}, 'empty': []} obj = cleanup_absent_fields(obj) assert 'y' not in obj assert 'z' not in obj assert 'l' not in obj assert 'z1' in obj assert 'b' not in obj['z1'] assert 'a' not in obj['z1'] assert 'empty' not in obj
def main(): argument_specs = dict(http_method=dict( required=True, choices=['get', 'put', 'post', 'patch', 'delete']), path=dict(type='str', required=True), params=dict(type='dict'), data=dict(type='jsonarg'), timeout=dict(type='int', default=60)) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_AVI: return module.fail_json( msg=('Avi python API SDK (avisdk) is not installed. ' 'For more details visit https://github.com/avinetworks/sdk.')) tenant_uuid = module.params.get('tenant_uuid', None) api = ApiSession.get_session(module.params['controller'], module.params['username'], module.params['password'], tenant=module.params['tenant'], tenant_uuid=tenant_uuid) tenant = module.params.get('tenant', '') timeout = int(module.params.get('timeout')) # path is a required argument path = module.params.get('path', '') params = module.params.get('params', None) data = module.params.get('data', None) # Get the api_version from module. api_version = module.params.get('api_version', '16.4') if data is not None: data = json.loads(data) method = module.params['http_method'] existing_obj = None changed = method != 'get' gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) if method == 'post': # need to check if object already exists. In that case # change the method to be put gparams['name'] = data['name'] rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) try: existing_obj = rsp.json()['results'][0] except IndexError: # object is not found pass else: # object is present method = 'put' path += '/' + existing_obj['uuid'] if method == 'put': # put can happen with when full path is specified or it is put + post if existing_obj is None: using_collection = False if (len(path.split('/')) == 1) and ('name' in data): gparams['name'] = data['name'] using_collection = True rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) rsp_data = rsp.json() if using_collection: if rsp_data['results']: existing_obj = rsp_data['results'][0] path += '/' + existing_obj['uuid'] else: method = 'post' else: if rsp.status_code == 404: method = 'post' else: existing_obj = rsp_data if existing_obj: changed = not avi_obj_cmp(data, existing_obj) cleanup_absent_fields(data) if method == 'patch': rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if (method == 'put' and changed) or (method != 'put'): fn = getattr(api, method) rsp = fn(path, tenant=tenant, tenant_uuid=tenant, timeout=timeout, params=params, data=data, api_version=api_version) else: rsp = None if method == 'delete' and rsp.status_code == 404: changed = False rsp.status_code = 200 if method == 'patch' and existing_obj and rsp.status_code < 299: # Ideally the comparison should happen with the return values # from the patch API call. However, currently Avi API are # returning different hostname when GET is used vs Patch. # tracked as AV-12561 if path.startswith('pool'): time.sleep(1) gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) new_obj = rsp.json() changed = not avi_obj_cmp(new_obj, existing_obj) if rsp is None: return module.exit_json(changed=changed, obj=existing_obj) return ansible_return(module, rsp, changed, req=data)
def main(): argument_specs = dict(http_method=dict( required=True, choices=['get', 'put', 'post', 'patch', 'delete']), path=dict(type='str', required=True), params=dict(type='dict'), data=dict(type='jsonarg'), timeout=dict(type='int', default=60)) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_AVI: return module.fail_json(msg=( 'Avi python API SDK (avisdk>=17.1) or requests is not installed. ' 'For more details visit https://github.com/avinetworks/sdk.')) api_creds = AviCredentials() api_creds.update_from_ansible_module(module) api = ApiSession.get_session(api_creds.controller, api_creds.username, password=api_creds.password, timeout=api_creds.timeout, tenant=api_creds.tenant, tenant_uuid=api_creds.tenant_uuid, token=api_creds.token, port=api_creds.port) tenant_uuid = api_creds.tenant_uuid tenant = api_creds.tenant timeout = int(module.params.get('timeout')) # path is a required argument path = module.params.get('path', '') params = module.params.get('params', None) data = module.params.get('data', None) # Get the api_version from module. api_version = api_creds.api_version if data is not None: data = json.loads(data) method = module.params['http_method'] existing_obj = None changed = method != 'get' gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) # API methods not allowed api_get_not_allowed = ["cluster", "gslbsiteops", "server", "nsxt"] sub_api_get_not_allowed = ["scaleout", "scalein", "upgrade", "rollback"] api_post_not_allowed = ["alert", "fileservice"] api_put_not_allowed = ["backup"] if method == 'post' and not any( path.startswith(uri) for uri in api_post_not_allowed): # TODO: Above condition should be updated after AV-38981 is fixed # need to check if object already exists. In that case # change the method to be put try: using_collection = False if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any( path.endswith(uri) for uri in sub_api_get_not_allowed)): if 'name' in data: gparams['name'] = data['name'] using_collection = True if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any( path.endswith(uri) for uri in sub_api_get_not_allowed)): rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if using_collection: existing_obj = existing_obj['results'][0] except (IndexError, KeyError): # object is not found pass else: if (not any(path.startswith(uri) for uri in api_get_not_allowed) and not any( path.endswith(uri) for uri in sub_api_get_not_allowed)): # object is present method = 'put' path += '/' + existing_obj['uuid'] if method == 'put' and not any( path.startswith(uri) for uri in api_put_not_allowed): # put can happen with when full path is specified or it is put + post get_path = path data_for_cmp = data if existing_obj is None: using_collection = False if ((len(path.split('/')) == 1) and ('name' in data) and (not any(path.startswith(uri) for uri in api_get_not_allowed))): gparams['name'] = data['name'] using_collection = True if path.startswith('wafpolicy') and path.endswith( 'update-crs-rules'): get_path = path.rstrip('/update-crs-rules') data_for_cmp = deepcopy(data) if data else {} _ = data_for_cmp.pop("commit", None) rsp = api.get(get_path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) rsp_data = rsp.json() if using_collection: if rsp_data['results']: existing_obj = rsp_data['results'][0] path += '/' + existing_obj['uuid'] else: method = 'post' else: if rsp.status_code == 404: method = 'post' else: existing_obj = rsp_data if existing_obj: changed = not avi_obj_cmp(data_for_cmp, existing_obj) cleanup_absent_fields(data) if method == 'patch': rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if (method == 'put' and changed) or (method != 'put'): fn = getattr(api, method) rsp = fn(path, tenant=tenant, tenant_uuid=tenant, timeout=timeout, params=params, data=data, api_version=api_version) else: rsp = None if method == 'delete' and rsp.status_code == 404: changed = False rsp.status_code = 200 if method == 'patch' and existing_obj and rsp.status_code < 299: # Ideally the comparison should happen with the return values # from the patch API call. However, currently Avi API are # returning different hostname when GET is used vs Patch. # tracked as AV-12561 if path.startswith('pool'): time.sleep(1) gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) new_obj = rsp.json() changed = not avi_obj_cmp(new_obj, existing_obj) if rsp is None: return module.exit_json(changed=changed, obj=existing_obj) return ansible_return(module, rsp, changed, req=data)
def main(): argument_specs = dict( http_method=dict(required=True, choices=['get', 'put', 'post', 'patch', 'delete']), path=dict(type='str', required=True), params=dict(type='dict'), data=dict(type='jsonarg'), timeout=dict(type='int', default=60) ) argument_specs.update(avi_common_argument_spec()) module = AnsibleModule(argument_spec=argument_specs) if not HAS_AVI: return module.fail_json(msg=( 'Avi python API SDK (avisdk) is not installed. ' 'For more details visit https://github.com/avinetworks/sdk.')) tenant_uuid = module.params.get('tenant_uuid', None) api = ApiSession.get_session( module.params['controller'], module.params['username'], module.params['password'], tenant=module.params['tenant'], tenant_uuid=tenant_uuid) tenant = module.params.get('tenant', '') timeout = int(module.params.get('timeout')) # path is a required argument path = module.params.get('path', '') params = module.params.get('params', None) data = module.params.get('data', None) # Get the api_version from module. api_version = module.params.get('api_version', '16.4') if data is not None: data = json.loads(data) method = module.params['http_method'] existing_obj = None changed = method != 'get' gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) if method == 'post': # need to check if object already exists. In that case # change the method to be put gparams['name'] = data['name'] rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) try: existing_obj = rsp.json()['results'][0] except IndexError: # object is not found pass else: # object is present method = 'put' path += '/' + existing_obj['uuid'] if method == 'put': # put can happen with when full path is specified or it is put + post if existing_obj is None: using_collection = False if (len(path.split('/')) == 1) and ('name' in data): gparams['name'] = data['name'] using_collection = True rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) rsp_data = rsp.json() if using_collection: if rsp_data['results']: existing_obj = rsp_data['results'][0] path += '/' + existing_obj['uuid'] else: method = 'post' else: if rsp.status_code == 404: method = 'post' else: existing_obj = rsp_data if existing_obj: changed = not avi_obj_cmp(data, existing_obj) cleanup_absent_fields(data) if method == 'patch': rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) existing_obj = rsp.json() if (method == 'put' and changed) or (method != 'put'): fn = getattr(api, method) rsp = fn(path, tenant=tenant, tenant_uuid=tenant, timeout=timeout, params=params, data=data, api_version=api_version) else: rsp = None if method == 'delete' and rsp.status_code == 404: changed = False rsp.status_code = 200 if method == 'patch' and existing_obj and rsp.status_code < 299: # Ideally the comparison should happen with the return values # from the patch API call. However, currently Avi API are # returning different hostname when GET is used vs Patch. # tracked as AV-12561 if path.startswith('pool'): time.sleep(1) gparams = deepcopy(params) if params else {} gparams.update({'include_refs': '', 'include_name': ''}) rsp = api.get(path, tenant=tenant, tenant_uuid=tenant_uuid, params=gparams, api_version=api_version) new_obj = rsp.json() changed = not avi_obj_cmp(new_obj, existing_obj) if rsp is None: return module.exit_json(changed=changed, obj=existing_obj) return ansible_return(module, rsp, changed, req=data)
def main(): try: module = AnsibleModule(argument_spec=dict( controller=dict(required=True), username=dict(required=True), password=dict(required=True), tenant=dict(default='admin'), tenant_uuid=dict(default=''), state=dict(default='present', choices=['absent', 'present']), clear_on_max_retries=dict(type='int', ), dns_configs=dict(type='list', ), name=dict(type='str', ), owner_controller_cluster_uuid=dict(type='str', ), send_interval=dict(type='int', ), site_controller_clusters=dict(type='list', ), tenant_ref=dict(type='str', ), url=dict(type='str', ), uuid=dict(type='str', ), view_id=dict(type='int', ), ), ) api = ApiSession.get_session(module.params['controller'], module.params['username'], module.params['password'], tenant=module.params['tenant']) state = module.params['state'] name = module.params['name'] obj = deepcopy(module.params) obj.pop('state', None) obj.pop('controller', None) obj.pop('username', None) obj.pop('password', None) tenant = obj.pop('tenant', '') tenant_uuid = obj.pop('tenant_uuid', '') obj.pop('cloud_ref', None) purge_optional_fields(obj, module) if state == 'absent': try: rsp = api.delete_by_name('globallb', name, tenant=tenant, tenant_uuid=tenant_uuid) except ObjectNotFound: return module.exit_json(changed=False) if rsp.status_code == 204: return module.exit_json(changed=True) return module.fail_json(msg=rsp.text) existing_obj = api.get_object_by_name('globallb', name, tenant=tenant, tenant_uuid=tenant_uuid, params={ 'include_refs': '', 'include_name': '' }) changed = False rsp = None if existing_obj: # this is case of modify as object exists. should find out # if changed is true or not changed = not avi_obj_cmp(obj, existing_obj) cleanup_absent_fields(obj) if changed: obj_uuid = existing_obj['uuid'] rsp = api.put('globallb/%s' % obj_uuid, data=obj, tenant=tenant, tenant_uuid=tenant_uuid) else: changed = True rsp = api.post('globallb', data=obj, tenant=tenant, tenant_uuid=tenant_uuid) if rsp is None: return module.exit_json(changed=changed, obj=existing_obj) else: return ansible_return(module, rsp, changed) except: raise