bug fixes, preparing for unittesting
This commit is contained in:
parent
3061b54059
commit
2f5b5fcf6b
@ -1,2 +1,2 @@
|
|||||||
__version__ = "2.1.3"
|
__version__ = "2.1.4"
|
||||||
|
|
||||||
|
@ -69,14 +69,18 @@ class configfile:
|
|||||||
self.profiles = config["profiles"]
|
self.profiles = config["profiles"]
|
||||||
if not os.path.exists(self.key):
|
if not os.path.exists(self.key):
|
||||||
self._createkey(self.key)
|
self._createkey(self.key)
|
||||||
self.privatekey = RSA.import_key(open(self.key).read())
|
with open(self.key) as f:
|
||||||
|
self.privatekey = RSA.import_key(f.read())
|
||||||
|
f.close()
|
||||||
self.publickey = self.privatekey.publickey()
|
self.publickey = self.privatekey.publickey()
|
||||||
|
|
||||||
|
|
||||||
def _loadconfig(self, conf):
|
def _loadconfig(self, conf):
|
||||||
#Loads config file
|
#Loads config file
|
||||||
jsonconf = open(conf)
|
jsonconf = open(conf)
|
||||||
return json.load(jsonconf)
|
jsondata = json.load(jsonconf)
|
||||||
|
jsonconf.close()
|
||||||
|
return jsondata
|
||||||
|
|
||||||
def _createconfig(self, conf):
|
def _createconfig(self, conf):
|
||||||
#Create config file
|
#Create config file
|
||||||
@ -87,7 +91,9 @@ class configfile:
|
|||||||
f.close()
|
f.close()
|
||||||
os.chmod(conf, 0o600)
|
os.chmod(conf, 0o600)
|
||||||
jsonconf = open(conf)
|
jsonconf = open(conf)
|
||||||
return json.load(jsonconf)
|
jsondata = json.load(jsonconf)
|
||||||
|
jsonconf.close()
|
||||||
|
return jsondata
|
||||||
|
|
||||||
def _saveconfig(self, conf):
|
def _saveconfig(self, conf):
|
||||||
#Save config file
|
#Save config file
|
||||||
@ -106,6 +112,7 @@ class configfile:
|
|||||||
f.write(key.export_key('PEM'))
|
f.write(key.export_key('PEM'))
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod(keyfile, 0o600)
|
os.chmod(keyfile, 0o600)
|
||||||
|
return key
|
||||||
|
|
||||||
def _explode_unique(self, unique):
|
def _explode_unique(self, unique):
|
||||||
#Divide unique name into folder, subfolder and id
|
#Divide unique name into folder, subfolder and id
|
||||||
|
@ -129,9 +129,13 @@ class connapp:
|
|||||||
#Function called when connecting or managing nodes.
|
#Function called when connecting or managing nodes.
|
||||||
if not self.case and args.data != None:
|
if not self.case and args.data != None:
|
||||||
args.data = args.data.lower()
|
args.data = args.data.lower()
|
||||||
if args.action == "version":
|
actions = {"version": self._version, "connect": self._connect, "debug": self._connect, "add": self._add, "del": self._del, "mod": self._mod, "show": self._show}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _version(self, args):
|
||||||
print(__version__)
|
print(__version__)
|
||||||
if args.action == "connect" or args.action == "debug":
|
|
||||||
|
def _connect(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
matches = self.nodes
|
matches = self.nodes
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
@ -156,7 +160,8 @@ class connapp:
|
|||||||
node.interact(debug = True)
|
node.interact(debug = True)
|
||||||
else:
|
else:
|
||||||
node.interact()
|
node.interact()
|
||||||
elif args.action == "del":
|
|
||||||
|
def _del(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -169,6 +174,8 @@ class connapp:
|
|||||||
exit(2)
|
exit(2)
|
||||||
question = [inquirer.Confirm("delete", message="Are you sure you want to delete {}?".format(matches[0]))]
|
question = [inquirer.Confirm("delete", message="Are you sure you want to delete {}?".format(matches[0]))]
|
||||||
confirm = inquirer.prompt(question)
|
confirm = inquirer.prompt(question)
|
||||||
|
if confirm == None:
|
||||||
|
exit(7)
|
||||||
if confirm["delete"]:
|
if confirm["delete"]:
|
||||||
uniques = self.config._explode_unique(matches[0])
|
uniques = self.config._explode_unique(matches[0])
|
||||||
if args.data.startswith("@"):
|
if args.data.startswith("@"):
|
||||||
@ -177,7 +184,8 @@ class connapp:
|
|||||||
self.config._connections_del(**uniques)
|
self.config._connections_del(**uniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} deleted succesfully".format(matches[0]))
|
print("{} deleted succesfully".format(matches[0]))
|
||||||
elif args.action == "add":
|
|
||||||
|
def _add(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -209,7 +217,6 @@ class connapp:
|
|||||||
self.config._folder_add(**uniques)
|
self.config._folder_add(**uniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data))
|
print("{} added succesfully".format(args.data))
|
||||||
|
|
||||||
if type == "node":
|
if type == "node":
|
||||||
nodefolder = args.data.partition("@")
|
nodefolder = args.data.partition("@")
|
||||||
nodefolder = "@" + nodefolder[2]
|
nodefolder = "@" + nodefolder[2]
|
||||||
@ -230,7 +237,8 @@ class connapp:
|
|||||||
self.config._connections_add(**newnode)
|
self.config._connections_add(**newnode)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data))
|
print("{} added succesfully".format(args.data))
|
||||||
elif args.action == "show":
|
|
||||||
|
def _show(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -246,7 +254,8 @@ class connapp:
|
|||||||
print(k + ":")
|
print(k + ":")
|
||||||
for i in v:
|
for i in v:
|
||||||
print(" - " + i)
|
print(" - " + i)
|
||||||
elif args.action == "mod":
|
|
||||||
|
def _mod(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -277,7 +286,10 @@ class connapp:
|
|||||||
#Function called when managing profiles
|
#Function called when managing profiles
|
||||||
if not self.case:
|
if not self.case:
|
||||||
args.data[0] = args.data[0].lower()
|
args.data[0] = args.data[0].lower()
|
||||||
if args.action == "del":
|
actions = {"add": self._profile_add, "del": self._profile_del, "mod": self._profile_mod, "show": self._profile_show}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _profile_del(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -296,7 +308,8 @@ class connapp:
|
|||||||
self.config._profiles_del(id = matches[0])
|
self.config._profiles_del(id = matches[0])
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} deleted succesfully".format(matches[0]))
|
print("{} deleted succesfully".format(matches[0]))
|
||||||
elif args.action == "show":
|
|
||||||
|
def _profile_show(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -309,7 +322,8 @@ class connapp:
|
|||||||
print(k + ":")
|
print(k + ":")
|
||||||
for i in v:
|
for i in v:
|
||||||
print(" - " + i)
|
print(" - " + i)
|
||||||
elif args.action == "add":
|
|
||||||
|
def _profile_add(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) > 0:
|
if len(matches) > 0:
|
||||||
print("Profile {} Already exist".format(matches[0]))
|
print("Profile {} Already exist".format(matches[0]))
|
||||||
@ -320,7 +334,8 @@ class connapp:
|
|||||||
self.config._profiles_add(**newprofile)
|
self.config._profiles_add(**newprofile)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data[0]))
|
print("{} added succesfully".format(args.data[0]))
|
||||||
elif args.action == "mod":
|
|
||||||
|
def _profile_mod(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -344,9 +359,13 @@ class connapp:
|
|||||||
|
|
||||||
def _func_others(self, args):
|
def _func_others(self, args):
|
||||||
#Function called when using other commands
|
#Function called when using other commands
|
||||||
if args.command == "ls":
|
actions = {"ls": self._ls, "move": self._mvcp, "cp": self._mvcp, "bulk": self._bulk, "completion": self._completion, "case": self._case, "fzf": self._fzf, "idletime": self._idletime}
|
||||||
|
return actions.get(args.command)(args)
|
||||||
|
|
||||||
|
def _ls(self, args):
|
||||||
print(*getattr(self, args.data), sep="\n")
|
print(*getattr(self, args.data), sep="\n")
|
||||||
elif args.command == "move" or args.command == "cp":
|
|
||||||
|
def _mvcp(self, args):
|
||||||
if not self.case:
|
if not self.case:
|
||||||
args.data[0] = args.data[0].lower()
|
args.data[0] = args.data[0].lower()
|
||||||
args.data[1] = args.data[1].lower()
|
args.data[1] = args.data[1].lower()
|
||||||
@ -374,11 +393,10 @@ class connapp:
|
|||||||
if args.command == "move":
|
if args.command == "move":
|
||||||
self.config._connections_del(**olduniques)
|
self.config._connections_del(**olduniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
if args.command == "move":
|
action = "moved" if args.command == "move" else "copied"
|
||||||
print("{} moved succesfully to {}".format(args.data[0],args.data[1]))
|
print("{} {} succesfully to {}".format(args.data[0],action, args.data[1]))
|
||||||
if args.command == "cp":
|
|
||||||
print("{} copied succesfully to {}".format(args.data[0],args.data[1]))
|
def _bulk(self, args):
|
||||||
elif args.command == "bulk":
|
|
||||||
newnodes = self._questions_bulk()
|
newnodes = self._questions_bulk()
|
||||||
if newnodes == False:
|
if newnodes == False:
|
||||||
exit(7)
|
exit(7)
|
||||||
@ -421,32 +439,44 @@ class connapp:
|
|||||||
print("Succesfully added {} nodes".format(count))
|
print("Succesfully added {} nodes".format(count))
|
||||||
else:
|
else:
|
||||||
print("0 nodes added")
|
print("0 nodes added")
|
||||||
else:
|
|
||||||
if args.command == "completion":
|
def _completion(self, args):
|
||||||
if args.data[0] == "bash":
|
if args.data[0] == "bash":
|
||||||
print(self._help("bashcompletion"))
|
print(self._help("bashcompletion"))
|
||||||
elif args.data[0] == "zsh":
|
elif args.data[0] == "zsh":
|
||||||
print(self._help("zshcompletion"))
|
print(self._help("zshcompletion"))
|
||||||
else:
|
|
||||||
if args.command == "case":
|
def _case(self, args):
|
||||||
if args.data[0] == "true":
|
if args.data[0] == "true":
|
||||||
args.data[0] = True
|
args.data[0] = True
|
||||||
elif args.data[0] == "false":
|
elif args.data[0] == "false":
|
||||||
args.data[0] = False
|
args.data[0] = False
|
||||||
if args.command == "fzf":
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _fzf(self, args):
|
||||||
if args.data[0] == "true":
|
if args.data[0] == "true":
|
||||||
args.data[0] = True
|
args.data[0] = True
|
||||||
elif args.data[0] == "false":
|
elif args.data[0] == "false":
|
||||||
args.data[0] = False
|
args.data[0] = False
|
||||||
if args.command == "idletime":
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _idletime(self, args):
|
||||||
if args.data[0] < 0:
|
if args.data[0] < 0:
|
||||||
args.data[0] = 0
|
args.data[0] = 0
|
||||||
self.config.config[args.command] = args.data[0]
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _change_settings(self, name, value):
|
||||||
|
self.config.config[name] = value
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("Config saved")
|
print("Config saved")
|
||||||
|
|
||||||
def _func_run(self, args):
|
def _func_run(self, args):
|
||||||
if len(args.data) > 1:
|
if len(args.data) > 1:
|
||||||
|
args.action = "noderun"
|
||||||
|
actions = {"noderun": self._node_run, "generate": self._yaml_generate, "run": self._yaml_run}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _node_run(self, args):
|
||||||
command = " ".join(args.data[1:])
|
command = " ".join(args.data[1:])
|
||||||
command = command.split("-")
|
command = command.split("-")
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.nodes))
|
matches = list(filter(lambda k: k == args.data[0], self.nodes))
|
||||||
@ -457,8 +487,8 @@ class connapp:
|
|||||||
node = self.node(matches[0],**node, config = self.config)
|
node = self.node(matches[0],**node, config = self.config)
|
||||||
node.run(command)
|
node.run(command)
|
||||||
print(node.output)
|
print(node.output)
|
||||||
else:
|
|
||||||
if args.action == "generate":
|
def _yaml_generate(self, args):
|
||||||
if os.path.exists(args.data[0]):
|
if os.path.exists(args.data[0]):
|
||||||
print("File {} already exists".format(args.data[0]))
|
print("File {} already exists".format(args.data[0]))
|
||||||
exit(14)
|
exit(14)
|
||||||
@ -468,6 +498,8 @@ class connapp:
|
|||||||
file.close()
|
file.close()
|
||||||
print("File {} generated succesfully".format(args.data[0]))
|
print("File {} generated succesfully".format(args.data[0]))
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
def _yaml_run(self, args):
|
||||||
try:
|
try:
|
||||||
with open(args.data[0]) as file:
|
with open(args.data[0]) as file:
|
||||||
scripts = yaml.load(file, Loader=yaml.FullLoader)
|
scripts = yaml.load(file, Loader=yaml.FullLoader)
|
||||||
@ -479,15 +511,14 @@ class connapp:
|
|||||||
args = {}
|
args = {}
|
||||||
try:
|
try:
|
||||||
action = script["action"]
|
action = script["action"]
|
||||||
except:
|
|
||||||
print("Action is mandatory")
|
|
||||||
exit(11)
|
|
||||||
try:
|
|
||||||
nodelist = script["nodes"]
|
nodelist = script["nodes"]
|
||||||
except:
|
args["commands"] = script["commands"]
|
||||||
print("Nodes list is mandatory")
|
output = script["output"]
|
||||||
|
if action == "test":
|
||||||
|
args["expected"] = script["expected"]
|
||||||
|
except KeyError as e:
|
||||||
|
print("'{}' is mandatory".format(e.args[0]))
|
||||||
exit(11)
|
exit(11)
|
||||||
# try:
|
|
||||||
for i in nodelist:
|
for i in nodelist:
|
||||||
if isinstance(i, dict):
|
if isinstance(i, dict):
|
||||||
name = list(i.keys())[0]
|
name = list(i.keys())[0]
|
||||||
@ -500,29 +531,6 @@ class connapp:
|
|||||||
this = self.config.getitem(i)
|
this = self.config.getitem(i)
|
||||||
nodes[i] = this
|
nodes[i] = this
|
||||||
nodes = self.connnodes(nodes, config = self.config)
|
nodes = self.connnodes(nodes, config = self.config)
|
||||||
# except:
|
|
||||||
# print("Failed getting nodes")
|
|
||||||
# exit(12)
|
|
||||||
try:
|
|
||||||
args["commands"] = script["commands"]
|
|
||||||
except:
|
|
||||||
print("Commands list is mandatory")
|
|
||||||
exit(11)
|
|
||||||
if action == "test":
|
|
||||||
try:
|
|
||||||
args["expected"] = script["expected"]
|
|
||||||
except:
|
|
||||||
print("Expected is mandatory with action 'test'")
|
|
||||||
exit(11)
|
|
||||||
try:
|
|
||||||
args["vars"] = script["variables"]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
output = script["output"]
|
|
||||||
except:
|
|
||||||
print("output is mandatory")
|
|
||||||
exit(11)
|
|
||||||
stdout = False
|
stdout = False
|
||||||
if output is None:
|
if output is None:
|
||||||
pass
|
pass
|
||||||
@ -530,14 +538,16 @@ class connapp:
|
|||||||
stdout = True
|
stdout = True
|
||||||
elif isinstance(output, str) and action == "run":
|
elif isinstance(output, str) and action == "run":
|
||||||
args["folder"] = output
|
args["folder"] = output
|
||||||
|
try:
|
||||||
|
args["vars"] = script["variables"]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
options = script["options"]
|
options = script["options"]
|
||||||
|
thisoptions = {k: v for k, v in options.items() if k in ["prompt", "parallel", "timeout"]}
|
||||||
|
args.update(thisoptions)
|
||||||
except:
|
except:
|
||||||
options = None
|
options = None
|
||||||
if options is not None:
|
|
||||||
thisoptions = {k: v for k, v in options.items() if k in ["prompt", "parallel", "timeout"]}
|
|
||||||
print(thisoptions)
|
|
||||||
args.update(thisoptions)
|
|
||||||
size = str(os.get_terminal_size())
|
size = str(os.get_terminal_size())
|
||||||
p = re.search(r'.*columns=([0-9]+)', size)
|
p = re.search(r'.*columns=([0-9]+)', size)
|
||||||
columns = int(p.group(1))
|
columns = int(p.group(1))
|
||||||
@ -1014,7 +1024,9 @@ tasks:
|
|||||||
'''
|
'''
|
||||||
if keyfile is None:
|
if keyfile is None:
|
||||||
keyfile = self.config.key
|
keyfile = self.config.key
|
||||||
key = RSA.import_key(open(keyfile).read())
|
with open(keyfile) as f:
|
||||||
|
key = RSA.import_key(f.read())
|
||||||
|
f.close()
|
||||||
publickey = key.publickey()
|
publickey = key.publickey()
|
||||||
encryptor = PKCS1_OAEP.new(publickey)
|
encryptor = PKCS1_OAEP.new(publickey)
|
||||||
password = encryptor.encrypt(password.encode("utf-8"))
|
password = encryptor.encrypt(password.encode("utf-8"))
|
||||||
|
@ -92,13 +92,14 @@ class node:
|
|||||||
else:
|
else:
|
||||||
self.password = [password]
|
self.password = [password]
|
||||||
|
|
||||||
def __passtx(self, passwords, *, keyfile=None):
|
def _passtx(self, passwords, *, keyfile=None):
|
||||||
# decrypts passwords, used by other methdos.
|
# decrypts passwords, used by other methdos.
|
||||||
dpass = []
|
dpass = []
|
||||||
if keyfile is None:
|
if keyfile is None:
|
||||||
keyfile = self.key
|
keyfile = self.key
|
||||||
if keyfile is not None:
|
if keyfile is not None:
|
||||||
key = RSA.import_key(open(keyfile).read())
|
with open(keyfile) as f:
|
||||||
|
key = RSA.import_key(f.read())
|
||||||
decryptor = PKCS1_OAEP.new(key)
|
decryptor = PKCS1_OAEP.new(key)
|
||||||
for passwd in passwords:
|
for passwd in passwords:
|
||||||
if not re.match('^b[\"\'].+[\"\']$', passwd):
|
if not re.match('^b[\"\'].+[\"\']$', passwd):
|
||||||
@ -147,6 +148,8 @@ class node:
|
|||||||
t = ansi_escape.sub('', t)
|
t = ansi_escape.sub('', t)
|
||||||
t = t.lstrip(" \n\r")
|
t = t.lstrip(" \n\r")
|
||||||
t = t.replace("\r","")
|
t = t.replace("\r","")
|
||||||
|
t = t.replace("\x0E","")
|
||||||
|
t = t.replace("\x0F","")
|
||||||
if var == False:
|
if var == False:
|
||||||
d = open(logfile, "w")
|
d = open(logfile, "w")
|
||||||
d.write(t)
|
d.write(t)
|
||||||
@ -163,7 +166,7 @@ class node:
|
|||||||
def _keepalive(self):
|
def _keepalive(self):
|
||||||
#Send keepalive ctrl+e when idletime passed without new inputs on interact
|
#Send keepalive ctrl+e when idletime passed without new inputs on interact
|
||||||
self.lastinput = time()
|
self.lastinput = time()
|
||||||
t = threading.currentThread()
|
t = threading.current_thread()
|
||||||
while True:
|
while True:
|
||||||
if time() - self.lastinput >= self.idletime:
|
if time() - self.lastinput >= self.idletime:
|
||||||
self.child.sendcontrol("e")
|
self.child.sendcontrol("e")
|
||||||
@ -208,7 +211,7 @@ class node:
|
|||||||
print(connect)
|
print(connect)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 10):
|
def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node and return the output.
|
Run a command or list of commands on the node and return the output.
|
||||||
|
|
||||||
@ -241,7 +244,7 @@ class node:
|
|||||||
default False.
|
default False.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
|
|
||||||
@ -292,7 +295,7 @@ class node:
|
|||||||
f.close()
|
f.close()
|
||||||
return connect
|
return connect
|
||||||
|
|
||||||
def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 10):
|
def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
||||||
|
|
||||||
@ -324,7 +327,7 @@ class node:
|
|||||||
need some special symbol.
|
need some special symbol.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
bool: true if expected value is found after running the commands
|
bool: true if expected value is found after running the commands
|
||||||
@ -390,7 +393,7 @@ class node:
|
|||||||
if self.logs != '':
|
if self.logs != '':
|
||||||
self.logfile = self._logfile()
|
self.logfile = self._logfile()
|
||||||
if self.password[0] != '':
|
if self.password[0] != '':
|
||||||
passwords = self.__passtx(self.password)
|
passwords = self._passtx(self.password)
|
||||||
else:
|
else:
|
||||||
passwords = []
|
passwords = []
|
||||||
expects = ['yes/no', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:|[u|U]sername:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
expects = ['yes/no', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:|[u|U]sername:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
||||||
@ -403,7 +406,7 @@ class node:
|
|||||||
if self.logs != '':
|
if self.logs != '':
|
||||||
self.logfile = self._logfile()
|
self.logfile = self._logfile()
|
||||||
if self.password[0] != '':
|
if self.password[0] != '':
|
||||||
passwords = self.__passtx(self.password)
|
passwords = self._passtx(self.password)
|
||||||
else:
|
else:
|
||||||
passwords = []
|
passwords = []
|
||||||
expects = ['[u|U]sername:', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
expects = ['[u|U]sername:', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
||||||
|
@ -424,14 +424,18 @@ __pdoc__ = {
|
|||||||
self.profiles = config["profiles"]
|
self.profiles = config["profiles"]
|
||||||
if not os.path.exists(self.key):
|
if not os.path.exists(self.key):
|
||||||
self._createkey(self.key)
|
self._createkey(self.key)
|
||||||
self.privatekey = RSA.import_key(open(self.key).read())
|
with open(self.key) as f:
|
||||||
|
self.privatekey = RSA.import_key(f.read())
|
||||||
|
f.close()
|
||||||
self.publickey = self.privatekey.publickey()
|
self.publickey = self.privatekey.publickey()
|
||||||
|
|
||||||
|
|
||||||
def _loadconfig(self, conf):
|
def _loadconfig(self, conf):
|
||||||
#Loads config file
|
#Loads config file
|
||||||
jsonconf = open(conf)
|
jsonconf = open(conf)
|
||||||
return json.load(jsonconf)
|
jsondata = json.load(jsonconf)
|
||||||
|
jsonconf.close()
|
||||||
|
return jsondata
|
||||||
|
|
||||||
def _createconfig(self, conf):
|
def _createconfig(self, conf):
|
||||||
#Create config file
|
#Create config file
|
||||||
@ -442,7 +446,9 @@ __pdoc__ = {
|
|||||||
f.close()
|
f.close()
|
||||||
os.chmod(conf, 0o600)
|
os.chmod(conf, 0o600)
|
||||||
jsonconf = open(conf)
|
jsonconf = open(conf)
|
||||||
return json.load(jsonconf)
|
jsondata = json.load(jsonconf)
|
||||||
|
jsonconf.close()
|
||||||
|
return jsondata
|
||||||
|
|
||||||
def _saveconfig(self, conf):
|
def _saveconfig(self, conf):
|
||||||
#Save config file
|
#Save config file
|
||||||
@ -461,6 +467,7 @@ __pdoc__ = {
|
|||||||
f.write(key.export_key('PEM'))
|
f.write(key.export_key('PEM'))
|
||||||
f.close()
|
f.close()
|
||||||
os.chmod(keyfile, 0o600)
|
os.chmod(keyfile, 0o600)
|
||||||
|
return key
|
||||||
|
|
||||||
def _explode_unique(self, unique):
|
def _explode_unique(self, unique):
|
||||||
#Divide unique name into folder, subfolder and id
|
#Divide unique name into folder, subfolder and id
|
||||||
@ -789,9 +796,13 @@ __pdoc__ = {
|
|||||||
#Function called when connecting or managing nodes.
|
#Function called when connecting or managing nodes.
|
||||||
if not self.case and args.data != None:
|
if not self.case and args.data != None:
|
||||||
args.data = args.data.lower()
|
args.data = args.data.lower()
|
||||||
if args.action == "version":
|
actions = {"version": self._version, "connect": self._connect, "debug": self._connect, "add": self._add, "del": self._del, "mod": self._mod, "show": self._show}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _version(self, args):
|
||||||
print(__version__)
|
print(__version__)
|
||||||
if args.action == "connect" or args.action == "debug":
|
|
||||||
|
def _connect(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
matches = self.nodes
|
matches = self.nodes
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
@ -816,7 +827,8 @@ __pdoc__ = {
|
|||||||
node.interact(debug = True)
|
node.interact(debug = True)
|
||||||
else:
|
else:
|
||||||
node.interact()
|
node.interact()
|
||||||
elif args.action == "del":
|
|
||||||
|
def _del(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -829,6 +841,8 @@ __pdoc__ = {
|
|||||||
exit(2)
|
exit(2)
|
||||||
question = [inquirer.Confirm("delete", message="Are you sure you want to delete {}?".format(matches[0]))]
|
question = [inquirer.Confirm("delete", message="Are you sure you want to delete {}?".format(matches[0]))]
|
||||||
confirm = inquirer.prompt(question)
|
confirm = inquirer.prompt(question)
|
||||||
|
if confirm == None:
|
||||||
|
exit(7)
|
||||||
if confirm["delete"]:
|
if confirm["delete"]:
|
||||||
uniques = self.config._explode_unique(matches[0])
|
uniques = self.config._explode_unique(matches[0])
|
||||||
if args.data.startswith("@"):
|
if args.data.startswith("@"):
|
||||||
@ -837,7 +851,8 @@ __pdoc__ = {
|
|||||||
self.config._connections_del(**uniques)
|
self.config._connections_del(**uniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} deleted succesfully".format(matches[0]))
|
print("{} deleted succesfully".format(matches[0]))
|
||||||
elif args.action == "add":
|
|
||||||
|
def _add(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -869,7 +884,6 @@ __pdoc__ = {
|
|||||||
self.config._folder_add(**uniques)
|
self.config._folder_add(**uniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data))
|
print("{} added succesfully".format(args.data))
|
||||||
|
|
||||||
if type == "node":
|
if type == "node":
|
||||||
nodefolder = args.data.partition("@")
|
nodefolder = args.data.partition("@")
|
||||||
nodefolder = "@" + nodefolder[2]
|
nodefolder = "@" + nodefolder[2]
|
||||||
@ -890,7 +904,8 @@ __pdoc__ = {
|
|||||||
self.config._connections_add(**newnode)
|
self.config._connections_add(**newnode)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data))
|
print("{} added succesfully".format(args.data))
|
||||||
elif args.action == "show":
|
|
||||||
|
def _show(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -906,7 +921,8 @@ __pdoc__ = {
|
|||||||
print(k + ":")
|
print(k + ":")
|
||||||
for i in v:
|
for i in v:
|
||||||
print(" - " + i)
|
print(" - " + i)
|
||||||
elif args.action == "mod":
|
|
||||||
|
def _mod(self, args):
|
||||||
if args.data == None:
|
if args.data == None:
|
||||||
print("Missing argument node")
|
print("Missing argument node")
|
||||||
exit(3)
|
exit(3)
|
||||||
@ -937,7 +953,10 @@ __pdoc__ = {
|
|||||||
#Function called when managing profiles
|
#Function called when managing profiles
|
||||||
if not self.case:
|
if not self.case:
|
||||||
args.data[0] = args.data[0].lower()
|
args.data[0] = args.data[0].lower()
|
||||||
if args.action == "del":
|
actions = {"add": self._profile_add, "del": self._profile_del, "mod": self._profile_mod, "show": self._profile_show}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _profile_del(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -956,7 +975,8 @@ __pdoc__ = {
|
|||||||
self.config._profiles_del(id = matches[0])
|
self.config._profiles_del(id = matches[0])
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} deleted succesfully".format(matches[0]))
|
print("{} deleted succesfully".format(matches[0]))
|
||||||
elif args.action == "show":
|
|
||||||
|
def _profile_show(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -969,7 +989,8 @@ __pdoc__ = {
|
|||||||
print(k + ":")
|
print(k + ":")
|
||||||
for i in v:
|
for i in v:
|
||||||
print(" - " + i)
|
print(" - " + i)
|
||||||
elif args.action == "add":
|
|
||||||
|
def _profile_add(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) > 0:
|
if len(matches) > 0:
|
||||||
print("Profile {} Already exist".format(matches[0]))
|
print("Profile {} Already exist".format(matches[0]))
|
||||||
@ -980,7 +1001,8 @@ __pdoc__ = {
|
|||||||
self.config._profiles_add(**newprofile)
|
self.config._profiles_add(**newprofile)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("{} added succesfully".format(args.data[0]))
|
print("{} added succesfully".format(args.data[0]))
|
||||||
elif args.action == "mod":
|
|
||||||
|
def _profile_mod(self, args):
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
matches = list(filter(lambda k: k == args.data[0], self.profiles))
|
||||||
if len(matches) == 0:
|
if len(matches) == 0:
|
||||||
print("{} not found".format(args.data[0]))
|
print("{} not found".format(args.data[0]))
|
||||||
@ -1004,9 +1026,13 @@ __pdoc__ = {
|
|||||||
|
|
||||||
def _func_others(self, args):
|
def _func_others(self, args):
|
||||||
#Function called when using other commands
|
#Function called when using other commands
|
||||||
if args.command == "ls":
|
actions = {"ls": self._ls, "move": self._mvcp, "cp": self._mvcp, "bulk": self._bulk, "completion": self._completion, "case": self._case, "fzf": self._fzf, "idletime": self._idletime}
|
||||||
|
return actions.get(args.command)(args)
|
||||||
|
|
||||||
|
def _ls(self, args):
|
||||||
print(*getattr(self, args.data), sep="\n")
|
print(*getattr(self, args.data), sep="\n")
|
||||||
elif args.command == "move" or args.command == "cp":
|
|
||||||
|
def _mvcp(self, args):
|
||||||
if not self.case:
|
if not self.case:
|
||||||
args.data[0] = args.data[0].lower()
|
args.data[0] = args.data[0].lower()
|
||||||
args.data[1] = args.data[1].lower()
|
args.data[1] = args.data[1].lower()
|
||||||
@ -1034,11 +1060,10 @@ __pdoc__ = {
|
|||||||
if args.command == "move":
|
if args.command == "move":
|
||||||
self.config._connections_del(**olduniques)
|
self.config._connections_del(**olduniques)
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
if args.command == "move":
|
action = "moved" if args.command == "move" else "copied"
|
||||||
print("{} moved succesfully to {}".format(args.data[0],args.data[1]))
|
print("{} {} succesfully to {}".format(args.data[0],action, args.data[1]))
|
||||||
if args.command == "cp":
|
|
||||||
print("{} copied succesfully to {}".format(args.data[0],args.data[1]))
|
def _bulk(self, args):
|
||||||
elif args.command == "bulk":
|
|
||||||
newnodes = self._questions_bulk()
|
newnodes = self._questions_bulk()
|
||||||
if newnodes == False:
|
if newnodes == False:
|
||||||
exit(7)
|
exit(7)
|
||||||
@ -1081,32 +1106,44 @@ __pdoc__ = {
|
|||||||
print("Succesfully added {} nodes".format(count))
|
print("Succesfully added {} nodes".format(count))
|
||||||
else:
|
else:
|
||||||
print("0 nodes added")
|
print("0 nodes added")
|
||||||
else:
|
|
||||||
if args.command == "completion":
|
def _completion(self, args):
|
||||||
if args.data[0] == "bash":
|
if args.data[0] == "bash":
|
||||||
print(self._help("bashcompletion"))
|
print(self._help("bashcompletion"))
|
||||||
elif args.data[0] == "zsh":
|
elif args.data[0] == "zsh":
|
||||||
print(self._help("zshcompletion"))
|
print(self._help("zshcompletion"))
|
||||||
else:
|
|
||||||
if args.command == "case":
|
def _case(self, args):
|
||||||
if args.data[0] == "true":
|
if args.data[0] == "true":
|
||||||
args.data[0] = True
|
args.data[0] = True
|
||||||
elif args.data[0] == "false":
|
elif args.data[0] == "false":
|
||||||
args.data[0] = False
|
args.data[0] = False
|
||||||
if args.command == "fzf":
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _fzf(self, args):
|
||||||
if args.data[0] == "true":
|
if args.data[0] == "true":
|
||||||
args.data[0] = True
|
args.data[0] = True
|
||||||
elif args.data[0] == "false":
|
elif args.data[0] == "false":
|
||||||
args.data[0] = False
|
args.data[0] = False
|
||||||
if args.command == "idletime":
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _idletime(self, args):
|
||||||
if args.data[0] < 0:
|
if args.data[0] < 0:
|
||||||
args.data[0] = 0
|
args.data[0] = 0
|
||||||
self.config.config[args.command] = args.data[0]
|
self._change_settings(args.command, args.data[0])
|
||||||
|
|
||||||
|
def _change_settings(self, name, value):
|
||||||
|
self.config.config[name] = value
|
||||||
self.config._saveconfig(self.config.file)
|
self.config._saveconfig(self.config.file)
|
||||||
print("Config saved")
|
print("Config saved")
|
||||||
|
|
||||||
def _func_run(self, args):
|
def _func_run(self, args):
|
||||||
if len(args.data) > 1:
|
if len(args.data) > 1:
|
||||||
|
args.action = "noderun"
|
||||||
|
actions = {"noderun": self._node_run, "generate": self._yaml_generate, "run": self._yaml_run}
|
||||||
|
return actions.get(args.action)(args)
|
||||||
|
|
||||||
|
def _node_run(self, args):
|
||||||
command = " ".join(args.data[1:])
|
command = " ".join(args.data[1:])
|
||||||
command = command.split("-")
|
command = command.split("-")
|
||||||
matches = list(filter(lambda k: k == args.data[0], self.nodes))
|
matches = list(filter(lambda k: k == args.data[0], self.nodes))
|
||||||
@ -1117,8 +1154,8 @@ __pdoc__ = {
|
|||||||
node = self.node(matches[0],**node, config = self.config)
|
node = self.node(matches[0],**node, config = self.config)
|
||||||
node.run(command)
|
node.run(command)
|
||||||
print(node.output)
|
print(node.output)
|
||||||
else:
|
|
||||||
if args.action == "generate":
|
def _yaml_generate(self, args):
|
||||||
if os.path.exists(args.data[0]):
|
if os.path.exists(args.data[0]):
|
||||||
print("File {} already exists".format(args.data[0]))
|
print("File {} already exists".format(args.data[0]))
|
||||||
exit(14)
|
exit(14)
|
||||||
@ -1128,6 +1165,8 @@ __pdoc__ = {
|
|||||||
file.close()
|
file.close()
|
||||||
print("File {} generated succesfully".format(args.data[0]))
|
print("File {} generated succesfully".format(args.data[0]))
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
def _yaml_run(self, args):
|
||||||
try:
|
try:
|
||||||
with open(args.data[0]) as file:
|
with open(args.data[0]) as file:
|
||||||
scripts = yaml.load(file, Loader=yaml.FullLoader)
|
scripts = yaml.load(file, Loader=yaml.FullLoader)
|
||||||
@ -1139,15 +1178,14 @@ __pdoc__ = {
|
|||||||
args = {}
|
args = {}
|
||||||
try:
|
try:
|
||||||
action = script["action"]
|
action = script["action"]
|
||||||
except:
|
|
||||||
print("Action is mandatory")
|
|
||||||
exit(11)
|
|
||||||
try:
|
|
||||||
nodelist = script["nodes"]
|
nodelist = script["nodes"]
|
||||||
except:
|
args["commands"] = script["commands"]
|
||||||
print("Nodes list is mandatory")
|
output = script["output"]
|
||||||
|
if action == "test":
|
||||||
|
args["expected"] = script["expected"]
|
||||||
|
except KeyError as e:
|
||||||
|
print("'{}' is mandatory".format(e.args[0]))
|
||||||
exit(11)
|
exit(11)
|
||||||
# try:
|
|
||||||
for i in nodelist:
|
for i in nodelist:
|
||||||
if isinstance(i, dict):
|
if isinstance(i, dict):
|
||||||
name = list(i.keys())[0]
|
name = list(i.keys())[0]
|
||||||
@ -1160,29 +1198,6 @@ __pdoc__ = {
|
|||||||
this = self.config.getitem(i)
|
this = self.config.getitem(i)
|
||||||
nodes[i] = this
|
nodes[i] = this
|
||||||
nodes = self.connnodes(nodes, config = self.config)
|
nodes = self.connnodes(nodes, config = self.config)
|
||||||
# except:
|
|
||||||
# print("Failed getting nodes")
|
|
||||||
# exit(12)
|
|
||||||
try:
|
|
||||||
args["commands"] = script["commands"]
|
|
||||||
except:
|
|
||||||
print("Commands list is mandatory")
|
|
||||||
exit(11)
|
|
||||||
if action == "test":
|
|
||||||
try:
|
|
||||||
args["expected"] = script["expected"]
|
|
||||||
except:
|
|
||||||
print("Expected is mandatory with action 'test'")
|
|
||||||
exit(11)
|
|
||||||
try:
|
|
||||||
args["vars"] = script["variables"]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
output = script["output"]
|
|
||||||
except:
|
|
||||||
print("output is mandatory")
|
|
||||||
exit(11)
|
|
||||||
stdout = False
|
stdout = False
|
||||||
if output is None:
|
if output is None:
|
||||||
pass
|
pass
|
||||||
@ -1190,14 +1205,16 @@ __pdoc__ = {
|
|||||||
stdout = True
|
stdout = True
|
||||||
elif isinstance(output, str) and action == "run":
|
elif isinstance(output, str) and action == "run":
|
||||||
args["folder"] = output
|
args["folder"] = output
|
||||||
|
try:
|
||||||
|
args["vars"] = script["variables"]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
options = script["options"]
|
options = script["options"]
|
||||||
|
thisoptions = {k: v for k, v in options.items() if k in ["prompt", "parallel", "timeout"]}
|
||||||
|
args.update(thisoptions)
|
||||||
except:
|
except:
|
||||||
options = None
|
options = None
|
||||||
if options is not None:
|
|
||||||
thisoptions = {k: v for k, v in options.items() if k in ["prompt", "parallel", "timeout"]}
|
|
||||||
print(thisoptions)
|
|
||||||
args.update(thisoptions)
|
|
||||||
size = str(os.get_terminal_size())
|
size = str(os.get_terminal_size())
|
||||||
p = re.search(r'.*columns=([0-9]+)', size)
|
p = re.search(r'.*columns=([0-9]+)', size)
|
||||||
columns = int(p.group(1))
|
columns = int(p.group(1))
|
||||||
@ -1674,7 +1691,9 @@ tasks:
|
|||||||
'''
|
'''
|
||||||
if keyfile is None:
|
if keyfile is None:
|
||||||
keyfile = self.config.key
|
keyfile = self.config.key
|
||||||
key = RSA.import_key(open(keyfile).read())
|
with open(keyfile) as f:
|
||||||
|
key = RSA.import_key(f.read())
|
||||||
|
f.close()
|
||||||
publickey = key.publickey()
|
publickey = key.publickey()
|
||||||
encryptor = PKCS1_OAEP.new(publickey)
|
encryptor = PKCS1_OAEP.new(publickey)
|
||||||
password = encryptor.encrypt(password.encode("utf-8"))
|
password = encryptor.encrypt(password.encode("utf-8"))
|
||||||
@ -1720,7 +1739,9 @@ tasks:
|
|||||||
'''
|
'''
|
||||||
if keyfile is None:
|
if keyfile is None:
|
||||||
keyfile = self.config.key
|
keyfile = self.config.key
|
||||||
key = RSA.import_key(open(keyfile).read())
|
with open(keyfile) as f:
|
||||||
|
key = RSA.import_key(f.read())
|
||||||
|
f.close()
|
||||||
publickey = key.publickey()
|
publickey = key.publickey()
|
||||||
encryptor = PKCS1_OAEP.new(publickey)
|
encryptor = PKCS1_OAEP.new(publickey)
|
||||||
password = encryptor.encrypt(password.encode("utf-8"))
|
password = encryptor.encrypt(password.encode("utf-8"))
|
||||||
@ -1937,13 +1958,14 @@ tasks:
|
|||||||
else:
|
else:
|
||||||
self.password = [password]
|
self.password = [password]
|
||||||
|
|
||||||
def __passtx(self, passwords, *, keyfile=None):
|
def _passtx(self, passwords, *, keyfile=None):
|
||||||
# decrypts passwords, used by other methdos.
|
# decrypts passwords, used by other methdos.
|
||||||
dpass = []
|
dpass = []
|
||||||
if keyfile is None:
|
if keyfile is None:
|
||||||
keyfile = self.key
|
keyfile = self.key
|
||||||
if keyfile is not None:
|
if keyfile is not None:
|
||||||
key = RSA.import_key(open(keyfile).read())
|
with open(keyfile) as f:
|
||||||
|
key = RSA.import_key(f.read())
|
||||||
decryptor = PKCS1_OAEP.new(key)
|
decryptor = PKCS1_OAEP.new(key)
|
||||||
for passwd in passwords:
|
for passwd in passwords:
|
||||||
if not re.match('^b[\"\'].+[\"\']$', passwd):
|
if not re.match('^b[\"\'].+[\"\']$', passwd):
|
||||||
@ -1992,6 +2014,8 @@ tasks:
|
|||||||
t = ansi_escape.sub('', t)
|
t = ansi_escape.sub('', t)
|
||||||
t = t.lstrip(" \n\r")
|
t = t.lstrip(" \n\r")
|
||||||
t = t.replace("\r","")
|
t = t.replace("\r","")
|
||||||
|
t = t.replace("\x0E","")
|
||||||
|
t = t.replace("\x0F","")
|
||||||
if var == False:
|
if var == False:
|
||||||
d = open(logfile, "w")
|
d = open(logfile, "w")
|
||||||
d.write(t)
|
d.write(t)
|
||||||
@ -2008,7 +2032,7 @@ tasks:
|
|||||||
def _keepalive(self):
|
def _keepalive(self):
|
||||||
#Send keepalive ctrl+e when idletime passed without new inputs on interact
|
#Send keepalive ctrl+e when idletime passed without new inputs on interact
|
||||||
self.lastinput = time()
|
self.lastinput = time()
|
||||||
t = threading.currentThread()
|
t = threading.current_thread()
|
||||||
while True:
|
while True:
|
||||||
if time() - self.lastinput >= self.idletime:
|
if time() - self.lastinput >= self.idletime:
|
||||||
self.child.sendcontrol("e")
|
self.child.sendcontrol("e")
|
||||||
@ -2053,7 +2077,7 @@ tasks:
|
|||||||
print(connect)
|
print(connect)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 10):
|
def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node and return the output.
|
Run a command or list of commands on the node and return the output.
|
||||||
|
|
||||||
@ -2086,7 +2110,7 @@ tasks:
|
|||||||
default False.
|
default False.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
|
|
||||||
@ -2137,7 +2161,7 @@ tasks:
|
|||||||
f.close()
|
f.close()
|
||||||
return connect
|
return connect
|
||||||
|
|
||||||
def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 10):
|
def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
||||||
|
|
||||||
@ -2169,7 +2193,7 @@ tasks:
|
|||||||
need some special symbol.
|
need some special symbol.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
bool: true if expected value is found after running the commands
|
bool: true if expected value is found after running the commands
|
||||||
@ -2235,7 +2259,7 @@ tasks:
|
|||||||
if self.logs != '':
|
if self.logs != '':
|
||||||
self.logfile = self._logfile()
|
self.logfile = self._logfile()
|
||||||
if self.password[0] != '':
|
if self.password[0] != '':
|
||||||
passwords = self.__passtx(self.password)
|
passwords = self._passtx(self.password)
|
||||||
else:
|
else:
|
||||||
passwords = []
|
passwords = []
|
||||||
expects = ['yes/no', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:|[u|U]sername:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
expects = ['yes/no', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:|[u|U]sername:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
||||||
@ -2248,7 +2272,7 @@ tasks:
|
|||||||
if self.logs != '':
|
if self.logs != '':
|
||||||
self.logfile = self._logfile()
|
self.logfile = self._logfile()
|
||||||
if self.password[0] != '':
|
if self.password[0] != '':
|
||||||
passwords = self.__passtx(self.password)
|
passwords = self._passtx(self.password)
|
||||||
else:
|
else:
|
||||||
passwords = []
|
passwords = []
|
||||||
expects = ['[u|U]sername:', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
expects = ['[u|U]sername:', 'refused', 'supported', 'cipher', 'sage', 'timeout', 'unavailable', 'closed', '[p|P]assword:', r'>$|#$|\$$|>.$|#.$|\$.$', 'suspend', pexpect.EOF, pexpect.TIMEOUT, "No route to host", "resolve hostname", "no matching host key"]
|
||||||
@ -2352,7 +2376,7 @@ tasks:
|
|||||||
</details>
|
</details>
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="connpy.node.run"><code class="name flex">
|
<dt id="connpy.node.run"><code class="name flex">
|
||||||
<span>def <span class="ident">run</span></span>(<span>self, commands, vars=None, *, folder='', prompt='>$|#$|\\$$|>.$|#.$|\\$.$', stdout=False, timeout=10)</span>
|
<span>def <span class="ident">run</span></span>(<span>self, commands, vars=None, *, folder='', prompt='>$|#$|\\$$|>.$|#.$|\\$.$', stdout=False, timeout=20)</span>
|
||||||
</code></dt>
|
</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="desc"><p>Run a command or list of commands on the node and return the output.</p>
|
<div class="desc"><p>Run a command or list of commands on the node and return the output.</p>
|
||||||
@ -2382,7 +2406,7 @@ tasks:
|
|||||||
default False.
|
default False.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="returns">Returns:</h3>
|
<h3 id="returns">Returns:</h3>
|
||||||
<pre><code>str: Output of the commands you ran on the node.
|
<pre><code>str: Output of the commands you ran on the node.
|
||||||
@ -2391,7 +2415,7 @@ tasks:
|
|||||||
<summary>
|
<summary>
|
||||||
<span>Expand source code</span>
|
<span>Expand source code</span>
|
||||||
</summary>
|
</summary>
|
||||||
<pre><code class="python">def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 10):
|
<pre><code class="python">def run(self, commands, vars = None,*, folder = '', prompt = r'>$|#$|\$$|>.$|#.$|\$.$', stdout = False, timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node and return the output.
|
Run a command or list of commands on the node and return the output.
|
||||||
|
|
||||||
@ -2424,7 +2448,7 @@ tasks:
|
|||||||
default False.
|
default False.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
|
|
||||||
@ -2477,7 +2501,7 @@ tasks:
|
|||||||
</details>
|
</details>
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="connpy.node.test"><code class="name flex">
|
<dt id="connpy.node.test"><code class="name flex">
|
||||||
<span>def <span class="ident">test</span></span>(<span>self, commands, expected, vars=None, *, prompt='>$|#$|\\$$|>.$|#.$|\\$.$', timeout=10)</span>
|
<span>def <span class="ident">test</span></span>(<span>self, commands, expected, vars=None, *, prompt='>$|#$|\\$$|>.$|#.$|\\$.$', timeout=20)</span>
|
||||||
</code></dt>
|
</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="desc"><p>Run a command or list of commands on the node, then check if expected value appears on the output after the last command.</p>
|
<div class="desc"><p>Run a command or list of commands on the node, then check if expected value appears on the output after the last command.</p>
|
||||||
@ -2506,7 +2530,7 @@ tasks:
|
|||||||
need some special symbol.
|
need some special symbol.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="returns">Returns:</h3>
|
<h3 id="returns">Returns:</h3>
|
||||||
<pre><code>bool: true if expected value is found after running the commands
|
<pre><code>bool: true if expected value is found after running the commands
|
||||||
@ -2516,7 +2540,7 @@ tasks:
|
|||||||
<summary>
|
<summary>
|
||||||
<span>Expand source code</span>
|
<span>Expand source code</span>
|
||||||
</summary>
|
</summary>
|
||||||
<pre><code class="python">def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 10):
|
<pre><code class="python">def test(self, commands, expected, vars = None,*, prompt = r'>$|#$|\$$|>.$|#.$|\$.$', timeout = 20):
|
||||||
'''
|
'''
|
||||||
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
Run a command or list of commands on the node, then check if expected value appears on the output after the last command.
|
||||||
|
|
||||||
@ -2548,7 +2572,7 @@ tasks:
|
|||||||
need some special symbol.
|
need some special symbol.
|
||||||
|
|
||||||
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
- timeout (int):Time in seconds for expect to wait for prompt/EOF.
|
||||||
default 10.
|
default 20.
|
||||||
|
|
||||||
### Returns:
|
### Returns:
|
||||||
bool: true if expected value is found after running the commands
|
bool: true if expected value is found after running the commands
|
||||||
|
Loading…
Reference in New Issue
Block a user