def test_pipeerrors(self): """test piped stderrs """ p = CmdPipe(readonly=False) err1 = [] err2 = [] err3 = [] out = [] p.add(["ls", "/nonexistent1"], stderr_handler=lambda line: err1.append(line)) p.add(["ls", "/nonexistent2"], stderr_handler=lambda line: err2.append(line)) p.add(["ls", "/nonexistent3"], stderr_handler=lambda line: err3.append(line)) executed = p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual( err1, ["ls: cannot access '/nonexistent1': No such file or directory"]) self.assertEqual( err2, ["ls: cannot access '/nonexistent2': No such file or directory"]) self.assertEqual( err3, ["ls: cannot access '/nonexistent3': No such file or directory"]) self.assertEqual(out, []) self.assertTrue(executed) self.assertEqual(p.items[0]['process'].returncode, 2) self.assertEqual(p.items[1]['process'].returncode, 2) self.assertEqual(p.items[2]['process'].returncode, 2)
def test_single(self): """single process stdout and stderr""" p=CmdPipe(readonly=False, inp=None) err=[] out=[] p.add(CmdItem(["ls", "-d", "/", "/", "/nonexistent"], stderr_handler=lambda line: err.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,2))) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err, ["ls: cannot access '/nonexistent': No such file or directory"]) self.assertEqual(out, ["/","/"]) self.assertIsNone(executed)
def test_input(self): """test stdinput""" p=CmdPipe(readonly=False, inp="test") err=[] out=[] p.add(CmdItem(["cat"], stderr_handler=lambda line: err.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,0))) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err, []) self.assertEqual(out, ["test"]) self.assertIsNone(executed)
def test_input(self): """test stdinput""" p = CmdPipe(readonly=False, inp="test") err = [] out = [] p.add(["echo", "test"], stderr_handler=lambda line: err.append(line)) executed = p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err, []) self.assertEqual(out, ["test"]) self.assertTrue(executed) self.assertEqual(p.items[0]['process'].returncode, 0)
def test_readonly_execute(self): """everything readonly, just should execute""" p=CmdPipe(readonly=True) err1=[] err2=[] out=[] def true_exit(exit_code): return True p.add(CmdItem(["echo", "test1"], stderr_handler=lambda line: err1.append(line), exit_handler=true_exit, readonly=True)) p.add(CmdItem(["echo", "test2"], stderr_handler=lambda line: err2.append(line), exit_handler=true_exit, readonly=True)) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(out, ["test2"]) self.assertTrue(executed)
def test_readonly_skip(self): """one command not readonly, skip""" p=CmdPipe(readonly=True) err1=[] err2=[] out=[] p.add(CmdItem(["echo", "test1"], stderr_handler=lambda line: err1.append(line), readonly=False)) p.add(CmdItem(["echo", "test2"], stderr_handler=lambda line: err2.append(line), readonly=True)) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(out, []) self.assertTrue(executed)
def test_exitcode(self): """test piped exitcodes """ p=CmdPipe(readonly=False) err1=[] err2=[] err3=[] out=[] p.add(CmdItem(["bash", "-c", "exit 1"], stderr_handler=lambda line: err1.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,1))) p.add(CmdItem(["bash", "-c", "exit 2"], stderr_handler=lambda line: err2.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,2))) p.add(CmdItem(["bash", "-c", "exit 3"], stderr_handler=lambda line: err3.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,3))) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(err3, []) self.assertEqual(out, []) self.assertIsNone(executed)
def test_pipe(self): """test piped""" p=CmdPipe(readonly=False) err1=[] err2=[] err3=[] out=[] p.add(CmdItem(["echo", "test"], stderr_handler=lambda line: err1.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,0))) p.add(CmdItem(["tr", "e", "E"], stderr_handler=lambda line: err2.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,0))) p.add(CmdItem(["tr", "t", "T"], stderr_handler=lambda line: err3.append(line), exit_handler=lambda exit_code: self.assertEqual(exit_code,0))) executed=p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(err3, []) self.assertEqual(out, ["TEsT"]) self.assertIsNone(executed) #test str representation as well self.assertEqual(str(p), "(echo test) | (tr e E) | (tr t T)")
def test_readonly_execute(self): """everything readonly, just should execute""" p = CmdPipe(readonly=True) err1 = [] err2 = [] out = [] p.add(["echo", "test1"], stderr_handler=lambda line: err1.append(line), readonly=True) p.add(["echo", "test2"], stderr_handler=lambda line: err2.append(line), readonly=True) executed = p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(out, ["test2"]) self.assertTrue(executed) self.assertEqual(p.items[0]['process'].returncode, 0) self.assertEqual(p.items[1]['process'].returncode, 0)
def test_pipe(self): """test piped""" p = CmdPipe(readonly=False) err1 = [] err2 = [] err3 = [] out = [] p.add(["echo", "test"], stderr_handler=lambda line: err1.append(line)) p.add(["tr", "e", "E"], stderr_handler=lambda line: err2.append(line)) p.add(["tr", "t", "T"], stderr_handler=lambda line: err3.append(line)) executed = p.execute(stdout_handler=lambda line: out.append(line)) self.assertEqual(err1, []) self.assertEqual(err2, []) self.assertEqual(err3, []) self.assertEqual(out, ["TEsT"]) self.assertTrue(executed) self.assertEqual(p.items[0]['process'].returncode, 0) self.assertEqual(p.items[1]['process'].returncode, 0) self.assertEqual(p.items[2]['process'].returncode, 0) #test str representation as well self.assertEqual(str(p), "(echo test) | (tr e E) | (tr t T)")
def run(self, cmd, inp=None, tab_split=False, valid_exitcodes=None, readonly=False, hide_errors=False, return_stderr=False, pipe=False): """run a command on the node , checks output and parses/handle output and returns it :param cmd: the actual command, should be a list, where the first item is the command and the rest are parameters. :param pipe: return CmdPipe instead of executing it. :param inp: Can be None, a string or a CmdPipe that was previously returned. :param tab_split: split tabbed files in output into a list :param valid_exitcodes: list of valid exit codes for this command (checks exit code of both sides of a pipe) Use [] to accept all exit codes. Default [0] :param readonly: make this True if the command doesn't make any changes and is safe to execute in testmode :param hide_errors: don't show stderr output as error, instead show it as debugging output (use to hide expected errors) :param return_stderr: return both stdout and stderr as a tuple. (normally only returns stdout) """ # create new pipe? if not isinstance(inp, CmdPipe): p = CmdPipe(self.readonly, inp) else: # add stuff to existing pipe p = inp # stderr parser error_lines = [] def stderr_handler(line): if tab_split: error_lines.append(line.rstrip().split('\t')) else: error_lines.append(line.rstrip()) self._parse_stderr(line, hide_errors) # add command to pipe encoded_cmd = self._remote_cmd(cmd) p.add(cmd=encoded_cmd, readonly=readonly, stderr_handler=stderr_handler) # return pipe instead of executing? if pipe: return p # stdout parser output_lines = [] def stdout_handler(line): if tab_split: output_lines.append(line.rstrip().split('\t')) else: output_lines.append(line.rstrip()) self._parse_stdout(line) if p.should_execute(): self.debug("CMD > {}".format(p)) else: self.debug("CMDSKIP> {}".format(p)) # execute and verify exit codes if p.execute( stdout_handler=stdout_handler) and valid_exitcodes is not []: if valid_exitcodes is None: valid_exitcodes = [0] item_nr = 1 for item in p.items: exit_code = item['process'].returncode if self.debug_output: self.debug("EXIT{} > {}".format(item_nr, exit_code)) if exit_code not in valid_exitcodes: raise (subprocess.CalledProcessError( exit_code, " ".join(item['cmd']))) item_nr = item_nr + 1 if return_stderr: return output_lines, error_lines else: return output_lines