blob: e9e118db6b6ea3f467bae443859dba8a21ef87eb [file] [log] [blame]
koder aka kdanilove06762a2015-03-22 23:32:09 +02001import re
koder aka kdanilov3a6633e2015-03-26 18:20:00 +02002import getpass
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +02003import logging
koder aka kdanilov962ee5f2016-12-19 02:40:08 +02004from typing import List, Dict, Any
koder aka kdanilov22d134e2016-11-08 11:33:19 +02005
koder aka kdanilove06762a2015-03-22 23:32:09 +02006
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +02007from . import utils
koder aka kdanilov73084622016-11-16 21:51:08 +02008from .common_types import IPAddr
koder aka kdanilov7f59d562016-12-26 01:34:23 +02009from .result_classes import IStorable
koder aka kdanilove06762a2015-03-22 23:32:09 +020010
11
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +020012logger = logging.getLogger("wally")
13
14
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020015class URIsNamespace:
16 class ReParts:
koder aka kdanilove06762a2015-03-22 23:32:09 +020017 user_rr = "[^:]*?"
koder aka kdanilov7e0f7cf2015-05-01 17:24:35 +030018 host_rr = "[^:@]*?"
koder aka kdanilove06762a2015-03-22 23:32:09 +020019 port_rr = "\\d+"
20 key_file_rr = "[^:@]*"
21 passwd_rr = ".*?"
22
23 re_dct = ReParts.__dict__
24
25 for attr_name, val in re_dct.items():
26 if attr_name.endswith('_rr'):
27 new_rr = "(?P<{0}>{1})".format(attr_name[:-3], val)
28 setattr(ReParts, attr_name, new_rr)
29
30 re_dct = ReParts.__dict__
31
32 templs = [
33 "^{host_rr}$",
koder aka kdanilov7e0f7cf2015-05-01 17:24:35 +030034 "^{host_rr}:{port_rr}$",
koder aka kdanilov416b87a2015-05-12 00:26:04 +030035 "^{host_rr}::{key_file_rr}$",
36 "^{host_rr}:{port_rr}:{key_file_rr}$",
koder aka kdanilov7e0f7cf2015-05-01 17:24:35 +030037 "^{user_rr}@{host_rr}$",
38 "^{user_rr}@{host_rr}:{port_rr}$",
koder aka kdanilove06762a2015-03-22 23:32:09 +020039 "^{user_rr}@{host_rr}::{key_file_rr}$",
40 "^{user_rr}@{host_rr}:{port_rr}:{key_file_rr}$",
koder aka kdanilov7e0f7cf2015-05-01 17:24:35 +030041 "^{user_rr}:{passwd_rr}@{host_rr}$",
42 "^{user_rr}:{passwd_rr}@{host_rr}:{port_rr}$",
koder aka kdanilove06762a2015-03-22 23:32:09 +020043 ]
44
koder aka kdanilov22d134e2016-11-08 11:33:19 +020045 uri_reg_exprs = [] # type: List[str]
koder aka kdanilove06762a2015-03-22 23:32:09 +020046 for templ in templs:
47 uri_reg_exprs.append(templ.format(**re_dct))
48
49
koder aka kdanilov7f59d562016-12-26 01:34:23 +020050class ConnCreds(IStorable):
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020051 def __init__(self, host: str, user: str, passwd: str = None, port: str = '22',
koder aka kdanilov73084622016-11-16 21:51:08 +020052 key_file: str = None, key: bytes = None) -> None:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020053 self.user = user
54 self.passwd = passwd
koder aka kdanilove7e1a4d2016-12-17 20:29:52 +020055 self.addr = IPAddr(host, int(port))
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020056 self.key_file = key_file
koder aka kdanilov73084622016-11-16 21:51:08 +020057 self.key = key
koder aka kdanilov22d134e2016-11-08 11:33:19 +020058
59 def __str__(self) -> str:
koder aka kdanilov73084622016-11-16 21:51:08 +020060 return "{}@{}:{}".format(self.user, self.addr.host, self.addr.port)
koder aka kdanilov22d134e2016-11-08 11:33:19 +020061
koder aka kdanilove7e1a4d2016-12-17 20:29:52 +020062 def __repr__(self) -> str:
63 return str(self)
64
koder aka kdanilov7f59d562016-12-26 01:34:23 +020065 def raw(self) -> Dict[str, Any]:
66 return {
67 'user': self.user,
68 'host': self.addr.host,
69 'port': self.addr.port,
70 'passwd': self.passwd,
71 'key_file': self.key_file
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020072 }
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020073
74 @classmethod
koder aka kdanilov7f59d562016-12-26 01:34:23 +020075 def fromraw(cls, data) -> 'ConnCreds':
76 return cls(**data)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020077
koder aka kdanilov22d134e2016-11-08 11:33:19 +020078
koder aka kdanilov22d134e2016-11-08 11:33:19 +020079def parse_ssh_uri(uri: str) -> ConnCreds:
koder aka kdanilov3d2bc4f2016-11-12 18:31:18 +020080 """Parse ssh connection URL from one of following form
81 [ssh://]user:passwd@host[:port]
82 [ssh://][user@]host[:port][:key_file]
83 """
koder aka kdanilove06762a2015-03-22 23:32:09 +020084
koder aka kdanilov4d4771c2015-04-23 01:32:02 +030085 if uri.startswith("ssh://"):
86 uri = uri[len("ssh://"):]
87
koder aka kdanilov22d134e2016-11-08 11:33:19 +020088 for rr in URIsNamespace.uri_reg_exprs:
koder aka kdanilove06762a2015-03-22 23:32:09 +020089 rrm = re.match(rr, uri)
90 if rrm is not None:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020091 params = {"user": getpass.getuser()} # type: Dict[str, str]
koder aka kdanilove7e1a4d2016-12-17 20:29:52 +020092 params.update(rrm.groupdict())
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +020093 params['host'] = utils.to_ip(params['host'])
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020094 return ConnCreds(**params) # type: ignore
koder aka kdanilov652cd802015-04-13 12:21:07 +030095
koder aka kdanilove06762a2015-03-22 23:32:09 +020096 raise ValueError("Can't parse {0!r} as ssh uri value".format(uri))
97
98