def setUp(self): self.adapter = requests_mock.Adapter() self.aos = Session(Config.test_server) self.aos.api.requests.mount('http://%s' % Config.test_server, self.adapter) self.adapter.register_uri( 'GET', '/api/versions/api', json=dict(version=Config.test_server_version)) self.adapter.register_uri( 'POST', '/api/user/login', json=dict(token=Config.test_auth_token)) # generally enable the probe step to pass patch.object(self.aos.api, 'probe', return_value=True).start()
def main(): module = AnsibleModule( argument_spec=dict(session=dict(required=True, type="dict"), collection=dict(required=True), src=dict(required=False), name=dict(required=False), dest=dict(require=False))) if not HAS_AOS_PYEZ: module.fail_json(msg='aos-pyez is not installed. Please see details ' 'here: https://github.com/Apstra/aos-pyez') margs = module.params auth = margs['session'] resources = None aos = Session() aos.api.resume(auth['url'], auth['headers']) try: resources = getattr(aos, margs['collection']) except NotImplementedError: module.fail_json(msg="unknown resource '%s'" % margs['collection']) if margs['dest'] and margs['name']: do_backup_resource(module, resources) elif 'src' in margs: do_load_resource(module, resources)
def main(): module = AnsibleModule( argument_spec=dict(session=dict(required=True, type="dict"), name=dict(required=True), location=dict(default=''))) if not HAS_AOS_PYEZ: module.fail_json(msg='aos-pyez is not installed. Please see details ' 'here: https://github.com/Apstra/aos-pyez') margs = module.params auth = margs['session'] try: aos = Session() aos.api.resume(auth['url'], auth['headers']) except LoginError: module.fail_json(msg="unable to login") dev = aos.Devices[margs['name']] if not dev.exists: module.fail_json(msg="unknown device '%s'" % margs['name']) if dev.is_approved: module.exit_json(changed=False) try: dev.approve(location=margs['location']) module.exit_json(changed=True) except (SessionError, SessionRqstError) as exc: module.fail_json(msg="unable to approve device '%s'" % exc.message)
def main(): module = AnsibleModule(argument_spec=dict( session=dict(required=True, type="dict"), name=dict(required=True), state=dict(choices=['present', 'absent', 'build-ready'], default='present'), timeout=dict(type="int", default=5), design_template=dict(required=False), reference_arch=dict(required=False))) if not HAS_AOS_PYEZ: module.fail_json(msg='aos-pyez is not installed. Please see details ' 'here: https://github.com/Apstra/aos-pyez') margs = module.params auth = margs['session'] aos, blueprint = None, None try: aos = Session() aos.api.resume(url=auth['url'], headers=auth['headers']) except LoginError as exc: module.fail_json(msg='Unable to login to AOS API: %s' % str(exc)) blueprint = aos.Blueprints[margs['name']] { 'absent': ensure_absent, 'present': ensure_present, 'build-ready': ensure_build_ready }.get(margs['state'])(aos, blueprint, module)
def main(): module = AnsibleModule( argument_spec=dict(session=dict(required=True, type="dict"), blueprint_name=dict(required=True), param_name=dict(required=True), param_map=dict(required=False, default="null"), param_value=dict(required=True, type="dict"), state=dict(choices=['present', 'absent', 'merged'], default='present'))) if not HAS_AOS_PYEZ: module.fail_json(msg='aos-pyez is not installed. Please see details ' 'here: https://github.com/Apstra/aos-pyez') margs = module.params auth = margs['session'] aos, blueprint, param = [None] * 3 try: aos = Session() aos.api.resume(url=auth['url'], headers=auth['headers']) except LoginError as exc: module.fail_json(msg='unable to login to AOS API: %s' % str(exc)) try: blueprint = aos.Blueprints[margs['blueprint_name']] if not blueprint.exists: module.fail_json( msg='blueprint %s does not exist.\n' 'known blueprints are [%s]' % (margs['blueprint_name'], ','.join(aos.Blueprints.names))) param = blueprint.params[margs['param_name']] except SessionError as exc: module.fail_json(msg='unable to access param %s: %s' % (margs['param_name'], str(exc))) try: param_value = margs['param_value'] param_map = margs['param_map'] param_map = json.loads(param_map) if param_map: if isinstance(param_map, dict): xf = CollectionValueMultiTransformer(aos, param_map) else: xf = CollectionValueTransformer(getattr(aos, param_map)) param_value = xf.xf_out(param_value) param.value = param_value except SessionError as exc: module.fail_json(msg='unable to write to param %s: %s' % (margs['param_name'], str(exc))) module.exit_json(changed=True)
def aos_login(module): mod_args = module.params aos = Session(server=mod_args['server'], port=mod_args['port'], user=mod_args['user'], passwd=mod_args['passwd']) try: aos.login() except aosExc.LoginServerUnreachableError: module.fail_json( msg="AOS-server [%s] API not available/reachable, check server" % aos.server) except aosExc.LoginAuthError: module.fail_json(msg="AOS-server login credentials failed") module.exit_json(changed=False, ansible_facts=dict(aos_session=aos.session), aos_session=dict(aos_session=aos.session))
def get_aos_session(module, auth): """ Resume an existing session and return an AOS object. Args: auth (dict): An AOS session as obtained by aos_login module blocks:: dict( token=<token>, server=<ip>, port=<port> ) Return: Aos object """ check_aos_version(module) aos = Session() aos.session = auth return aos
def main(): module = AnsibleModule( argument_spec=dict( session=dict(required=True, type="dict"), blueprint_name=dict(required=True), src=dict(required=False), state=dict(choices=['present', 'absent'], default='present')) ) if not HAS_AOS_PYEZ: module.fail_json(msg='aos-pyez is not installed. Please see details ' 'here: https://github.com/Apstra/aos-pyez') margs = module.params auth = margs['session'] aos, blueprint, param = [None] * 3 try: aos = Session() aos.api.resume(url=auth['url'], headers=auth['headers']) except LoginError as exc: module.fail_json(msg='unable to login to AOS API: %s' % str(exc)) blueprint = aos.Blueprints[margs['blueprint_name']] if not blueprint.exists: module.fail_json(msg='blueprint %s does not exist.\n' 'known blueprints are [%s]'% (margs['blueprint_name'], ','.join(aos.Blueprints.names))) { 'present': ensure_present, 'absent': ensure_absent }[margs['state']](module, blueprint)
def __init__(self): """ Main execution path """ if not HAS_AOS_PYEZ: raise Exception( 'aos-pyez is not installed. Please see details here: https://github.com/Apstra/aos-pyez' ) # Initialize inventory self.inventory = dict() # A list of groups and the hosts in that group self.inventory['_meta'] = dict() self.inventory['_meta']['hostvars'] = dict() # Read settings and parse CLI arguments self.read_settings() self.parse_cli_args() # ---------------------------------------------------- # Open session to AOS # ---------------------------------------------------- aos = Session(server=self.aos_server, port=self.aos_server_port, user=self.aos_username, passwd=self.aos_password) aos.login() # Save session information in variables of group all self.add_var_to_group('all', 'aos_session', aos.session) # Add the AOS server itself in the inventory self.add_host_to_group("all", 'aos') self.add_var_to_host("aos", "ansible_ssh_host", self.aos_server) self.add_var_to_host("aos", "ansible_ssh_pass", self.aos_password) self.add_var_to_host("aos", "ansible_ssh_user", self.aos_username) # ---------------------------------------------------- # Build the inventory # 2 modes are supported: device based or blueprint based # - For device based, the list of device is taken from the global device list # the serial ID will be used as the inventory_hostname # - For Blueprint based, the list of device is taken from the given blueprint # the Node name will be used as the inventory_hostname # ---------------------------------------------------- if self.aos_blueprint: bp = aos.Blueprints[self.aos_blueprint] if bp.exists is False: fail("Unable to find the Blueprint: %s" % self.aos_blueprint) for dev_name, dev_id in bp.params['devices'].value.items(): self.add_host_to_group('all', dev_name) device = aos.Devices.find(uid=dev_id) if 'facts' in device.value.keys(): self.add_device_facts_to_var(dev_name, device) # Define admin State and Status if 'user_config' in device.value.keys(): if 'admin_state' in device.value['user_config'].keys(): self.add_var_to_host( dev_name, 'admin_state', device.value['user_config']['admin_state']) self.add_device_status_to_var(dev_name, device) # Go over the contents data structure for node in bp.contents['system']['nodes']: if node['display_name'] == dev_name: self.add_host_to_group(node['role'], dev_name) # Check for additional attribute to import attributes_to_import = [ 'loopback_ip', 'asn', 'role', 'position', ] for attr in attributes_to_import: if attr in node.keys(): self.add_var_to_host(dev_name, attr, node[attr]) # if blueprint_interface is enabled in the configuration # Collect links information if self.aos_blueprint_int: interfaces = dict() for link in bp.contents['system']['links']: # each link has 2 sides [0,1], and it's unknown which one match this device # at first we assume, first side match(0) and peer is (1) peer_id = 1 for side in link['endpoints']: if side['display_name'] == dev_name: # import local information first int_name = side['interface'] # init dict interfaces[int_name] = dict() if 'ip' in side.keys(): interfaces[int_name]['ip'] = side['ip'] if 'interface' in side.keys(): interfaces[int_name]['name'] = side[ 'interface'] if 'display_name' in link['endpoints'][ peer_id].keys(): interfaces[int_name]['peer'] = link[ 'endpoints'][peer_id]['display_name'] if 'ip' in link['endpoints'][peer_id].keys(): interfaces[int_name]['peer_ip'] = link[ 'endpoints'][peer_id]['ip'] if 'type' in link['endpoints'][peer_id].keys(): interfaces[int_name]['peer_type'] = link[ 'endpoints'][peer_id]['type'] else: # if we haven't match the first time, prepare the peer_id # for the second loop iteration peer_id = 0 self.add_var_to_host(dev_name, 'interfaces', interfaces) else: for device in aos.Devices: # If not reacheable, create by key and # If reacheable, create by hostname self.add_host_to_group('all', device.name) # populate information for this host self.add_device_status_to_var(device.name, device) if 'user_config' in device.value.keys(): for key, value in device.value['user_config'].items(): self.add_var_to_host(device.name, key, value) # Based on device status online|offline, collect facts as well if device.value['status']['comm_state'] == 'on': if 'facts' in device.value.keys(): self.add_device_facts_to_var(device.name, device) # Check if device is associated with a blueprint # if it's create a new group if 'blueprint_active' in device.value['status'].keys(): if 'blueprint_id' in device.value['status'].keys(): bp = aos.Blueprints.find( uid=device.value['status']['blueprint_id']) if bp: self.add_host_to_group(bp.name, device.name) # ---------------------------------------------------- # Convert the inventory and return a JSON String # ---------------------------------------------------- data_to_print = "" data_to_print += self.json_format_dict(self.inventory, True) print(data_to_print)
class TestSession(AosPyEzCommonTestCase): """ Test cases to verify the functionality of the Session object, mainly focused around the various login pass/failure cases. """ def setUp(self): self.adapter = requests_mock.Adapter() self.aos = Session(Config.test_server) self.aos.api.requests.mount('http://%s' % Config.test_server, self.adapter) self.adapter.register_uri( 'GET', '/api/versions/api', json=dict(version=Config.test_server_version)) self.adapter.register_uri( 'POST', '/api/user/login', json=dict(token=Config.test_auth_token)) # generally enable the probe step to pass patch.object(self.aos.api, 'probe', return_value=True).start() def test_login_pass(self): self.aos.login() self.assertEquals(self.aos.session, Config.test_session) self.assertEquals(self.aos.token, Config.test_auth_token) self.assertEquals(self.aos.api.version['version'], Config.test_server_version) def test_login_no_server(self): had_server = self.aos.server self.aos.server = None try: self.aos.login() except LoginNoServerError: pass else: self.fail('LoginNoServerError not raised as expected') finally: self.aos.server = had_server def test_login_unreachable_server(self): try: # noinspection PyUnresolvedReferences with patch.object(self.aos.api, 'probe', return_value=False): self.aos.login() except LoginServerUnreachableError: pass else: self.fail('LoginServerUnreachableError not raised as expected') def test_login_bad_credentials(self): self.adapter.register_uri('POST', '/api/user/login', status_code=400) try: self.aos.login() except LoginAuthError: pass else: self.fail('LoginAuthError not raised as expected') # ##### ------------------------------------------------------------------- # ##### resume session test cases # ##### ------------------------------------------------------------------- @staticmethod def validate_token(request, context): context.status_code = [400, 200][int(request.headers['AUTHTOKEN'] == Config.test_auth_token)] return {} def test_login_resume_pass(self): self.adapter.register_uri('GET', '/api/user', json=self.validate_token) self.aos.session = Config.test_session def test_login_resume_bad_token(self): self.adapter.register_uri('GET', '/api/user', json=self.validate_token) try: bad_session = copy(Config.test_session) bad_session['token'] = 'i am a bad token' self.aos.session = bad_session except LoginAuthError: pass else: self.fail('LoginAuthError not raised as expected') def test_login_resume_bad_url(self): self.adapter.register_uri('GET', '/api/user', json=self.validate_token) try: bad_session = copy(Config.test_session) del bad_session['server'] self.aos.session = bad_session except LoginError: pass else: self.fail('LoginError not raised as expected') def test_login_resume_unreachable_server(self): self.adapter.register_uri('GET', '/api/user', json=self.validate_token) try: with patch.object(self.aos.api, 'probe', return_value=False): self.aos.session = Config.test_session except LoginServerUnreachableError: pass else: self.fail('LoginServerUnreachableError not raised as expected') # ##### ------------------------------------------------------------------- # ##### test probing against real target # ##### ------------------------------------------------------------------- def test_probe_real_target_ok(self): test_target = Session.Api() test_target.set_url(server='www.google.com', port=80) self.assertTrue(test_target.probe()) def test_probe_real_target_fail(self): test_target = Session.Api() test_target.set_url(server='www.google.com', port=81) self.assertFalse(test_target.probe()) # ##### ------------------------------------------------------------------- # ##### test misc properties # ##### ------------------------------------------------------------------- def test_property_token_missing(self): try: _ = self.aos.token except NoLoginError: pass else: self.assertTrue( False, msg='NoLoginError not raised as expected') def test_property_token_ok(self): self.aos.login() self.assertEquals(self.aos.token, Config.test_auth_token) def test_property_url_missing(self): try: _ = self.aos.url except NoLoginError: pass else: self.assertTrue( False, msg='NoLoginError not raised as expected') def test_property_url_ok(self): self.aos.login() _ = self.aos.url
def test_probe_real_target_fail(self): test_target = Session.Api() test_target.set_url(server='www.google.com', port=81) self.assertFalse(test_target.probe())
def test_probe_real_target_ok(self): test_target = Session.Api() test_target.set_url(server='www.google.com', port=80) self.assertTrue(test_target.probe())
def __init__(self): """ Main execution path """ if not HAS_AOS_PYEZ: raise Exception('aos-pyez is not installed. Please see details here: https://github.com/Apstra/aos-pyez') if not HAS_ARGPARSE: raise Exception('argparse is not installed. Please install the argparse library or upgrade to python-2.7') # Initialize inventory self.inventory = dict() # A list of groups and the hosts in that group self.inventory['_meta'] = dict() self.inventory['_meta']['hostvars'] = dict() # Read settings and parse CLI arguments self.read_settings() self.parse_cli_args() # ---------------------------------------------------- # Open session to AOS # ---------------------------------------------------- aos = Session(server=self.aos_server, port=self.aos_server_port, user=self.aos_username, passwd=self.aos_password) aos.login() # Save session information in variables of group all self.add_var_to_group('all', 'aos_session', aos.session) # Add the AOS server itself in the inventory self.add_host_to_group("all", 'aos') self.add_var_to_host("aos", "ansible_ssh_host", self.aos_server) self.add_var_to_host("aos", "ansible_ssh_pass", self.aos_password) self.add_var_to_host("aos", "ansible_ssh_user", self.aos_username) # ---------------------------------------------------- # Build the inventory # 2 modes are supported: device based or blueprint based # - For device based, the list of device is taken from the global device list # the serial ID will be used as the inventory_hostname # - For Blueprint based, the list of device is taken from the given blueprint # the Node name will be used as the inventory_hostname # ---------------------------------------------------- if self.aos_blueprint: bp = aos.Blueprints[self.aos_blueprint] if bp.exists is False: fail("Unable to find the Blueprint: %s" % self.aos_blueprint) for dev_name, dev_id in bp.params['devices'].value.items(): self.add_host_to_group('all', dev_name) device = aos.Devices.find(uid=dev_id) if 'facts' in device.value.keys(): self.add_device_facts_to_var(dev_name, device) # Define admin State and Status if 'user_config' in device.value.keys(): if 'admin_state' in device.value['user_config'].keys(): self.add_var_to_host(dev_name, 'admin_state', device.value['user_config']['admin_state']) self.add_device_status_to_var(dev_name, device) # Go over the contents data structure for node in bp.contents['system']['nodes']: if node['display_name'] == dev_name: self.add_host_to_group(node['role'], dev_name) # Check for additional attribute to import attributes_to_import = [ 'loopback_ip', 'asn', 'role', 'position', ] for attr in attributes_to_import: if attr in node.keys(): self.add_var_to_host(dev_name, attr, node[attr]) # if blueprint_interface is enabled in the configuration # Collect links information if self.aos_blueprint_int: interfaces = dict() for link in bp.contents['system']['links']: # each link has 2 sides [0,1], and it's unknown which one match this device # at first we assume, first side match(0) and peer is (1) peer_id = 1 for side in link['endpoints']: if side['display_name'] == dev_name: # import local information first int_name = side['interface'] # init dict interfaces[int_name] = dict() if 'ip' in side.keys(): interfaces[int_name]['ip'] = side['ip'] if 'interface' in side.keys(): interfaces[int_name]['name'] = side['interface'] if 'display_name' in link['endpoints'][peer_id].keys(): interfaces[int_name]['peer'] = link['endpoints'][peer_id]['display_name'] if 'ip' in link['endpoints'][peer_id].keys(): interfaces[int_name]['peer_ip'] = link['endpoints'][peer_id]['ip'] if 'type' in link['endpoints'][peer_id].keys(): interfaces[int_name]['peer_type'] = link['endpoints'][peer_id]['type'] else: # if we haven't match the first time, prepare the peer_id # for the second loop iteration peer_id = 0 self.add_var_to_host(dev_name, 'interfaces', interfaces) else: for device in aos.Devices: # If not reacheable, create by key and # If reacheable, create by hostname self.add_host_to_group('all', device.name) # populate information for this host self.add_device_status_to_var(device.name, device) if 'user_config' in device.value.keys(): for key, value in device.value['user_config'].items(): self.add_var_to_host(device.name, key, value) # Based on device status online|offline, collect facts as well if device.value['status']['comm_state'] == 'on': if 'facts' in device.value.keys(): self.add_device_facts_to_var(device.name, device) # Check if device is associated with a blueprint # if it's create a new group if 'blueprint_active' in device.value['status'].keys(): if 'blueprint_id' in device.value['status'].keys(): bp = aos.Blueprints.find(uid=device.value['status']['blueprint_id']) if bp: self.add_host_to_group(bp.name, device.name) # ---------------------------------------------------- # Convert the inventory and return a JSON String # ---------------------------------------------------- data_to_print = "" data_to_print += self.json_format_dict(self.inventory, True) print(data_to_print)
def __init__(self): """ Main execution path """ if not HAS_AOS_PYEZ: raise Exception( 'aos-pyez is not installed. Please see details here: https://github.com/Apstra/aos-pyez' ) # Initialize inventory self.inventory = dict() # A list of groups and the hosts in that group self.inventory['_meta'] = dict() self.inventory['_meta']['hostvars'] = dict() # Read settings and parse CLI arguments self.read_settings() self.parse_cli_args() # ---------------------------------------------------- # Open session to AOS # ---------------------------------------------------- aos = Session(server=self.aos_server, port=self.aos_server_port, user=self.aos_username, passwd=self.aos_password) aos.login() # ---------------------------------------------------- # Build the inventory # ---------------------------------------------------- for device in aos.Devices: # If not reacheable, create by key and # If reacheable, create by hostname self.add_host_to_group('all', device.name) # populate information for this host if 'status' in device.value.keys(): for key, value in device.value['status'].items(): self.add_var_to_host(device.name, key, value) if 'user_config' in device.value.keys(): for key, value in device.value['user_config'].items(): self.add_var_to_host(device.name, key, value) # Based on device status online|offline, collect facts as well if device.value['status']['comm_state'] == 'on': if 'facts' in device.value.keys(): # Populate variables for this host self.add_var_to_host(device.name, 'ansible_ssh_host', device.value['facts']['mgmt_ipaddr']) # self.add_host_to_group('all', device.name) for key, value in device.value['facts'].items(): self.add_var_to_host(device.name, key, value) if key == 'os_family': self.add_host_to_group(value, device.name) elif key == 'hw_model': self.add_host_to_group(value, device.name) # Check if device is associated with a blueprint # if it's create a new group if 'blueprint_active' in device.value['status'].keys(): if 'blueprint_id' in device.value['status'].keys(): bp = aos.Blueprints.find( method='id', key=device.value['status']['blueprint_id']) if bp: self.add_host_to_group(bp['display_name'], device.name) # ---------------------------------------------------- # Convert the inventory and return a JSON String # ---------------------------------------------------- data_to_print = "" data_to_print += self.json_format_dict(self.inventory, True) print(data_to_print)