Emulate SSH server for testing purposes - python

I have to write test for deployment script which uploads files through SSH, but I'd like to have it not depending on external servers configuration. This is how i see it:
Create 2 SSH daemons without authentication on different ports of loopback interface.
Run the deployment script on these two ports
The only question is how to run these dummy SSH daemons.
I use Python and Fabric.

If you want full control over the server's actions (e.g. in order to simulate various problem conditions and thereby do a really thorough testing) I recommend twisted: as this article shows, it makes it really easy to set up your own custom SSH server.
If you'd rather use an existing ssh server, pick one from the list here (or use the one that comes with your system, if any; or maybe sshwindows if you're on windows) and run it with subprocess from Python as a part of starting up your tests.

Another option is to spin up a dockerized container with sshd service running. You can use a docker image like these:
https://github.com/kabirbaidhya/fakeserver
https://github.com/panubo/docker-sshd.
I've used this for testing out a deployment script (made on top of fabric ).
Here's how you use it.
Pull the image.
➜ docker pull kabirbaidhya/fakeserver
Set authorized keys for the server.
➜ cat ~/.ssh/id_rsa.pub > /path/to/authorized_keys
Run the fakeserver.
➜ docker run -d -p 2222:22 \
-v "/path/to/authorized_keys:/etc/authorized_keys/tester" \
-e SSH_USERS="tester:1001:1001" \
--name=fakeserver kabirbaidhya/fakeserver
You can now use the fakeserver from any ssh client. For instance:
➜ ssh tester#localhost -p 2222
➜ ssh tester#localhost -p 2222 "echo 'Hello World'"
If this works, you can then use any ssh clients or scripts on top of paramiko or fabric to test against this mock server.
Hope this helps.

Reimplementing an SSH daemon is not trivial.
If your only problem is you don't want them depending on existing configurations, you can start up new sshd with -f to specify a specific configuration and -p to run on a given port.
You can use os.system to make calls to the shell:
os.system('sshd -f myconfig -p 22022')

Related

How to speed up execution of many commands on a single server via SSH?

I need to run many commands on the same server via SSH using Paramiko.
How can I speed up the execution.
Multiple SSH connections?
Is it possible to run commands in an asynchronous fashion?
How can this be done with paramiko?
Commands that need to be executed are not correlated. One command does not depend on the output of another.
For example:
ssh root#172.16.2.40
docker containers ps # get a list of containers
for container_id in containers:
docker inspect container_id # get details of each container
There maybe hundreds of docker containers running on a single server.
docker API is not an option for me. So running command via SSH is the only way.

How to watch xvfb session that's inside a docker on remote server from my local browser?

I'm running a docker (That I built on my own), that's docker running E2E tests.
The browser is up and running but I want to have another nice to have feature, I want the ability of watching the session online.
My docker run command is:
docker run -p 4444:4444 --name ${DOCKER_TAG_NAME}
-e Some_ENVs
-v Volume:Volume
--privileged
-d "{docker-registry}" >> /dev/null 2>&1
I'm able to export screenshots but in some cases it's not enough and the ability of watching what is the exact state of the test would be amazing.
I tried a lot of options but I came to a dead end, Any help would be great.
My tests are in Python 2.7
My Docker base is ubuntu:14.04
My environment is in AWS (If that's matter)
The docker runs on Ubuntu servers.
I know it a duplicate of this but no one answered him so...
There is a recent tool called Selenoid. It is launching browsers in Docker containers (i.e. headless as you require). It has a standalone UI capable to show live session screen via VNC. So you can launch multiple sessions in parallel and then look and even intercept actions happening in target browser. All this stuff perfectly works in cloud environment.
I have faced the same issue before with vnc, you need to know your xvfb/vnc in which port is using then open that port on you aws secuirty group once you done with that then you should be able to connect.
On my case i was starting selenium docker "https://github.com/elgalu/docker-selenium" and used this command to start the docker machine "docker run -d --name=grid -p 4444:24444 -p 5900:25900 \
-v /dev/shm:/dev/shm -e VNC_PASSWORD=hola \
-e SCREEN_WIDTH=1920 -e SCREEN_HEIGHT=1480 \
elgalu/selenium"
The VNC port as per the command is "5900" so i opened that port on instance security group, and connected using VNC viewer on port 5900

PyCharm add remote Python interpreter inside the Docker

So I have set up a docker on my laptop. I'm using Boot2Docker so I have one level of indirection to access the docker. In PyCharm, I can set a remote python interpreter via SSH but I'm not sure how to do it for dockers that can only be accessed via Boot2Docker?
Okay so to answer your question(s):
In PyCharm, I can set a remote python interpreter via SSH but I'm not sure how to do it for dockers that can only be accessed via Boot2Docker?
You need:
To ensure that you have SSH running in your container
There are many base images that include SSH. See: Dockerizing an SSH Daemon
Expose the SSH service to the Boot2Docker/VirtualBox VM.
docker run -d -p 2222:22 myimage ...
Setup PyCharm to connect to your Boot2Docker/VirtualBox VM.
boot2docker ip
Attaching to a running container is easy too!
$ boot2docker ssh
$ docker exec -i -t <cid> /bin/bash
Where <cid> is the Container ID or Name (if you used --name.

run ssh command remotely without redirecting output

I want to run a python script on my server (that python script has GUI). But I want to start it from ssh. Something like this:
ssh me#server -i my_key "nohup python script.py"
... > let the script run forever
BUT it complains "unable to access video driver" since it is trying to use my ssh terminal as output.
Can I somehow make my commands output run on server machine and not to my terminal... Basically something like "wake-on-lan functionality" -> tell the server you want something and he will do everything using its own system (not sending any output back)
What about
ssh me#server -i my_key "nohup python script.py >/dev/null 2>&1"
You can use redirection to some remote logfile instead of /dev/null of course.
? :)
EDIT: GUI applications on X usually use $DISPLAY variable to know where they should be displayed. Moreover, X11 display servers use authorization to permit or disallow applications connecting to its display. Commands
export DISPLAY=:0 && xhost +
may be helpful for you.
Isn't it possible for you to rather use python ssh extension instead of calling external application?
It would:
run as one process
guarantee that invocation will be the same among all possible system
lose the overhead from "execution"
send everything trough ssh (you won't have to worry about input like "; possibly local executed command)
If not, go with what Piotr Wades suggested.

Implement a remote command line interface using Ruby/Python

Are there any existing library for implementing a remote command line interface?
e.g.
Consider the case of gitolite, when you do a git push origin, it will ssh into the remote server and execute some code (namely hooks, no server is needed for the whole transaction.
What I want to archive is something like that, e.g.
./remote get_up_time
It will invoke ssh into the remote machine and do execute the script get_up_time already deployed
the ruby standard distribution provides DRb aka Distributed Ruby:
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html
Implementing your own script would be easy enough.
#!/bin/bash
ssh root#example.com "$1"
Then you could just call like:
./remote.sh get_up_time
Assuming that ssh is installed and that your public key is on the remote server (and thus, you do not need to provide a password), this would be a crude implementation:
#!/usr/bin/env ruby
host = ARGV.shift
command = ARGV.join(' ')
IO.popen("ssh #{host} \"#{command}\"") do |io|
io.sync = true
io.readlines.each { |line| puts line }
end
Usable like:
$ ./remote.rb www.example.com ls -l
You can expand this as needed to provide extra features, such as reading from stdin to provide ssh a password or something.
Although it appears there is "no server", there is certainly an sshd (a remote server) running on the remote system that allows this to work.
If you don't want to use ssh, you will need to use another server running on the remote machine or write your own.

Categories