Blackbox test with python of a ncurses python app via Paramiko - python

I'm in the strange position of being both the developer of a python utility for our project, and the tester of it.
The app is ready and now I want to write a couple of blackbox tests that connect to the server where it resides (the server itself is the product that we commercialize), and launch the python application.
The python app allows a minimal command line scripting (some parameters automatically launch functions that otherwise would require user interaction at the main menu). For the residual user interactions, I usually try bash syntax like this:
./app -f <<< $'parameter1\nparameter2\n\n'
And finally I redirect everything to >/dev/null.
If I do manual checks at the command line on the server (where I connect via SSH), everything works smoothly. The app launch lasts 30 seconds, and after 30 seconds I'm correctly returned to the prompt.
Now to the blackbox testing part. Here I'm also using python (Py.test framework), but the test code resides on another machine.
The test runner machine will connect to the Server under test via Paramiko libraries. I've already used this a lot in scripting other functionalities of the product, and it works quite well.
But the problem in this case is that the app under test that I wrote in python uses the NCurses library in its normal behaviour ("import curses"), and apparently when trying to launch this in the Py.test script:
import paramiko
...
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
client.connect(myhost, myuser, mypass, mytimeout)
client.exec_command("./app -f <<< $'parameter1\nparameter2\n\n' >/dev/null")
Regardless the redirection to /dev/null, the .exec_command() prints this to standard error out with a message about the curses initialization:
...
File "/my/path/to/app", line xxx, in curses_screen
scr = curses.initscr()
...
_curses.error: setupterm: could not find terminal
and finally the py.test script fails because the app execution crashed.
Is there some conflicts between curses (used by the app under test) and paramiko (used by the test script)? As I said, if I connect manually via SSH to the server where the app resides and launch the command line manually with the silent redirection to /dev/null, it works as I would expect.

ncurses really would like to do input/output to a terminal. /dev/null is not a terminal, and some terminal I/O mode changes will fail in that case. Occasionally someone connects the I/O to a socket, and ncurses will (usually) work in that situation.
In your environment, besides the lack of a terminal, it is possible that TERM is unset. That will make setupterm fail.
Setupterm could not find terminal, in Python program using curses
wrong error from curses.wrapper if curses initialization fails

Related

Pytest/Fabric not using SSH agent when debugging in PyCharm

I am writing some infrastructure tests using pytest and fabric. Generally this is working. I run a test from the command line that executes a fabric task on a remote server and asserts something about the result of that task. The task is executed using my running SSH agent.
However, when I try to debug my tests in PyCharm the fabric tasks fail with the following exception
Fatal error: Needed to prompt for a connection or sudo password, but input would be ambiguous in parallel mode
This difference in behavior leads me to believe something isn't configured properly in my debug configuration. I have made sure that environment variables in debug config includes the SSH agent PID.

Opening third-party console and running commands

I am trying to write a script to open a third-party console application and run commands on Windows. The third-party console requires the two commands; 'connect' and 'run'. A typical input/output is shown below. This connects to the host server then runs a process indexed by three parameters (p1,p2,p3).
>connect server
Successfully connected to service.
>run p1 p2 p3
Successfully started.
FINISHED
The app does not allow me to execute both commands in one line using & as with cmd.
Despite reading the subprocess documentation I can't figure out how to pass my two commands into the executable.
I am using Python 3.5, so I believe subprocess.run should be suitable for this task. The snippet below simply opens the third-party console. I have tried other code, linked at the bottom of the post, but I am unsure how to implement it for my purpose.
import subprocess
exe = r'C:\...\third_party_app.exe'
subprocess.run(exe)
Below are some of the SO resources that could be helpful that I have tried, and failed, to interpret.
https://stackoverflow.com/tags/subprocess/info
Python - How do I pass a string into subprocess.Popen (using the stdin argument)?

How to remote debug in PyCharm

The issue I'm facing right now:
I deploy Python code on a remote host via SSH
the scripts are passed some arguments and must be ran by a specific user
the PyCharm run/debug configuration that I create connects through SSH via a different user (can't connect with the user that actually runs the scripts)
I want to remote debug this code via PyCharm...I managed to do all configuration, I just get permission errors.
Are there any ways on how I can run/debug the scripts as a specific user (like sudo su - user)?
I've read about specifying some Python Interpeter options in PyCharm's remote/debug configuration, but didn't manage to get a working solution.
If you want an easy and more flexible way to get into the PyCharm debugger, rather than necessarily having a one-click "play" button in PyCharm, you can use the debug server functionality. I've used this in situations where running some Python code isn't as simple as running python ....
See the Remote debug with a Python Debug Server docs for more details, but here's a rough summary of how it works:
Upload & install remote debugging helper egg on your server (On OSX, these are found under /Applications/PyCharm.app/Contents/debug-eggs)
Setup remote debug server run configuration: click on the drop-down run configuration menu, select Edit configurations..., hit the + button, choose Python remote debug.
The details entered here (somewhat confusingly) tell the remote server running the Python script how to connect to your laptop's PyCharm instance.
set Local host name to your laptop's IP address
set port to any free port that you can use on your laptop (e.g. 8888)
Now follow the remaining instructions in that dialog box: copy-paste the import and pydevd.settrace(...) statements into your code, specifically where you want your code to "hit a breakpoint". This is basically the PyCharm equivalent of import pdb; pdb.set_trace(). Make sure the changed code is sync'ed to your server.
Hit the bug button (next to play; this starts the PyCharm debug server), and run your Python script just like you'd normally do, under whatever user, environment etc. When the breakpoint is hit, PyCharm should drop into debug mode.
I have this (finally) working with ssh RemoteForward open, like so:
ssh -R 5678:localhost:5678 user#<remotehost>
Then start the script in this ssh session. The python script host must connect to localhost:5678 and of course your local pycharm debugger must listen to 5678
(or whatever port you choose)

Creating a Python script that runs as a Windows service using sc.exe

I would like to create a Windows Service using a batch script for a Python script that I have written. I decided to do some experimenting with sc. Here is the line that I used:
sc create RoundTripService binPath="C:\Python27\python.exe C:\script.py" type=own error=ignore start=auto
Unfortunately, when I do so, the console is giving me a printout of the Description/Usage/Options, etc. of sc instead.
SC is overly strict about spaces in its command line and you are receiving the error because you have no space after the "binPath=" and "type=" components. Run
SC CREATE /?
at a DOS prompt to see how your command line should be constructed.
But even if you get SC to install python, you will run into the dreaded "Error 1053" when you attempt to start the service! This is because Python.exe is not a true Windows Service executable and can not react to the Windows Service Control Manager's request to start the service. You will need a "service wrapper" (like Microsoft's SRVANY, though it has some shortcomings) to intercept the requests from the Windows Service Control Manager and start your python script.

Execute remote python script via SSH

I want to execute a Python script on several (15+) remote machine using SSH. After invoking the script/command I need to disconnect ssh session and keep the processes running in background for as long as they are required to.
I have used Paramiko and PySSH in past so have no problems using them again. Only thing I need to know is how to disconnect a ssh session in python (since normally local script would wait for each remote machine to complete processing before moving on).
This might work, or something similar:
ssh user#remote.host nohup python scriptname.py &
Basically, have a look at the nohup command.
On Linux machines, you can run the script with 'at'.
echo "python scriptname.py" ¦ at now
If you are going to perform repetitive tasks on many hosts, like for example deploying software and running setup scripts, you should consider using something like Fabric
Fabric is a Python (2.5 or higher) library and command-line tool for
streamlining the use of SSH for application deployment or systems
administration tasks.
It provides a basic suite of operations for executing local or remote
shell commands (normally or via sudo) and uploading/downloading files,
as well as auxiliary functionality such as prompting the running user
for input, or aborting execution.
Typical use involves creating a Python module containing one or more
functions, then executing them via the fab command-line tool.
You can even use tmux in this scenario.
As per the tmux documentation:
tmux is a terminal multiplexer. It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more
From a tmux session, you can run a script, quit the terminal, log in again and check back as it keeps the session until the server restart.
How to configure tmux on a cloud server

Categories