def test_target(target, starget): t = Target.from_string(target) t = Target.from_string(t) assert str(t).startswith("http:") t = Target.from_string(starget) assert str(t).startswith("https:") with pytest.raises(ValueError): t = Target.from_string(":///_10:600000") t = Target("host.lab", "http", 80) assert str(t) == "http://host.lab" assert t.domain == "host.lab" t = Target("host", "http", 8080) assert str(t) == "http://host:8080" assert t.domain == "host.local" with pytest.raises(ValueError): Target("host", transport="bogus", port=6000) with pytest.raises(ValueError): Target("host", transport="http", port=600000)
def text_response(): request = prepare_request(["show hostname", "show version"], "text") response = { 'jsonrpc': '2.0', 'id': '45e8f5f4-7620-43c9-8407-da0a03bbcc50', 'result': [{ 'output': 'Hostname: rbf153\n' 'FQDN: rbf153.sjc.aristanetworks.com\n' }, { 'output': 'Arista DCS-7280CR2M-30-F\n' 'Hardware version: 20.01\n' 'Serial number: JAS18140236\n' 'System MAC address: 7483.ef02.a6fb\n\n' 'Software image version: 4.23.2.1F-DPE\n' 'Architecture: i686\n' 'Internal build version: 4.23.2.1F-DPE-16108061.42321F\n' 'Internal build ID: 73a5535d-c66e-4597-b6ed-8999e76b66ea\n\n' 'Uptime: 1 weeks, 6 days, 16 hours and 35 minutes\n' 'Total memory: 32890040 kB\n' 'Free memory: 25851572 kB\n\n' }] } return Target.from_string("localhost"), request, response
def json_response(): request = prepare_request(["show hostname", "show version"], "json") response = { 'jsonrpc': '2.0', 'id': '532c456f-0b5a-4e20-885b-0e838aa1bb57', 'result': [{ 'fqdn': 'rbf153.sjc.aristanetworks.com', 'hostname': 'rbf153' }, { 'memTotal': 32890040, 'uptime': 1181670.77, 'modelName': 'DCS-7280CR2M-30-F', 'internalVersion': '4.23.2.1F-DPE-16108061.42321F', 'mfgName': 'Arista', 'serialNumber': 'JAS18140236', 'systemMacAddress': '74:83:ef:02:a6:fb', 'bootupTimestamp': 1586324536.0, 'memFree': 25852932, 'version': '4.23.2.1F-DPE', 'architecture': 'i686', 'isIntlVersion': False, 'internalBuildId': '73a5535d-c66e-4597-b6ed-8999e76b66ea', 'hardwareRevision': '20.01' }] } return Target.from_string("localhost"), request, response
async def call(self, target: Union[str, Target], commands: List[Command], encoding: Optional[str] = None, **kwargs): """call commands to an eAPI target :param target: eAPI target (host, port) :param type: Target :param commands: List of `Command` objects :param type: list :param encoding: response encoding 'json' or 'text' (default: json) :param \*\*kwargs: other pass through `httpx` options :param type: dict """ target_: Target = Target.from_string(target) # get session defaults (set at login) options = self._eapi_sessions.get(target_.domain) or {} options.update(kwargs) request = prepare_request(commands, encoding) response = await self._call(target_.url + "/command-api", data=request, **options) return Response.from_rpc_response(target_, request, response.json())
def test_login_err(server): target = str(server.url) with Session() as sess: with pytest.raises(eapi.exceptions.EapiAuthenticationFailure): sess.login(target, auth=("sdfsf", "sfs")) with pytest.raises(httpx.HTTPError): sess._call(Target.from_string(target).url + "/login", None)
def logged_in(self, target: Union[str, Target], transport: Optional[str] = None) -> bool: """determines if session cookie is set""" target_: Target = Target.from_string(target) cookie = self._session.cookies.get("Session", domain=target_.domain) return True if cookie else False
def test_jsonrpc_error(session, server): target = str(server.url) tgt = Target.from_string(target) req = prepare_request(["show hostname"]) req["method"] = "bogus" resp = session._call(tgt.url + "/command-api", req) rresp = Response.from_rpc_response(tgt, req, resp.json()) assert rresp.code < 0
def jsonrpcerr_response(): response = { 'jsonrpc': '2.0', 'id': None, 'error': { 'message': "Expected field 'jsonrpc' not specified", 'code': -32600 } } return Target.from_string("localhost"), None, response
async def logout(self, target: Union[str, Target]) -> None: """Log out of an eAPI session :param target: eAPI target (host, port) :param type: Target """ target_: Target = Target.from_string(target) if target_.domain in self._eapi_sessions: del self._eapi_sessions[target_.domain] if self.logged_in(target): await self._call(target_.url + "/logout", data={})
def errored_response(): request = prepare_request(["show hostname", "show bogus"], "json") response = { 'jsonrpc': '2.0', 'id': '6585432e-2214-43d8-be6b-06bf68617aba', 'error': { 'data': [{ 'fqdn': 'veos3-782f', 'hostname': 'veos3-782f' }, { 'errors': ["Invalid input (at token 1: 'bogus')"] }], 'message': "CLI command 2 of 2 'show bogus' failed: invalid command", 'code': 1002 } } return Target.from_string("localhost"), request, response
def login(self, target: Union[str, Target], auth: Optional[Auth] = None) -> None: """Login to an eAPI session :param target: eAPI target (host, port) :param type: Target :param auth: username, password tuple :param type: Auth """ target_: Target = Target.from_string(target) if self.logged_in(target): return username, password = auth or self._session.auth payload = {"username": username, "password": password} resp = self._call(target_.url + "/login", data=payload) self._handle_login_response(target_, auth, resp)
def errored_text_response(): request = prepare_request(["show hostname", "show bogus"], "text") response = { 'jsonrpc': '2.0', 'id': '072cdc16-be82-4f98-9c42-549a954b5881', 'error': { 'data': [{ 'output': 'Hostname: veos3-782f\n' 'FQDN: veos3-782f\n' }, { 'output': "% Invalid input (at token 1: 'bogus')\n", 'errors': ["Invalid input (at token 1: 'bogus')"] }], 'message': "CLI command 2 of 2 'show bogus' failed: invalid command", 'code': 1002 } } return Target.from_string("localhost"), request, response
def test_http_error(session, server): target = str(server.url) t = Target.from_string(target) with pytest.raises(eapi.exceptions.EapiPathNotFoundError): session._call(t.url + "/badpath", {})