liftoff / GateOne

Gate One is an HTML5-powered terminal emulator and SSH client
http://liftoffsoftware.com/Products/GateOne
Other
6.27k stars 925 forks source link

Setting up GateOne with Selenium for function testing #262

Open l-parsons opened 11 years ago

l-parsons commented 11 years ago

Hi,

I was wondering if I could get some pointers setting up GateOne. I am looking at accessing a Linux application I use and using Selenium to create some functional tests.

What I need is:

  1. Automate SSH login with username and password.
  2. Creating Linux environmental variables from the web.
  3. Host initiated callback (scripts that the application currently sends back via the terminal with a special string that lets me know it's a script)

Any help with any of these items would be greatly appreciated, thanks.

liftoff commented 11 years ago

I've never used Selenium before but you can automate these tasks with Gate One via a plugin. You'd just make JavaScript calls like this:

GateOne.Terminal.sendString('somehost\n22\nusername\npassword\n');

...which would log you into the server in question. There's no client-side 'expect' functionality but the entire terminal screen is stored in GateOne.Terminal.terminals[1]['screen'] (replace 1 with the terminal number) as an array of strings (lines). So you can walk the array looking for, <span class="✈cursor"> to see which line is the 'current' one and scrape the entirety of the screen looking for whatever strings you like with a simple loop and timeouts.

Note to self: Add GateOne.Terminal.expect() because it shouldn't be too hard :yum:

If you want to assign environment variables whenever a terminal is opened you can do that with a plugin too... Just set your command (in 50terminal.conf) to something like:

"commands": ["my_script": "/path/to/my_script.sh VAR1 VAR2 VAR3"],
"default_command": "my_script",

Then create a plugin like this that transforms the command (e.g. gateone/applications/terminal/plugins/myplugin/myplugin.py):

def transform_comand(self, command):
    command = command.replace('VAR1', whatever1)
    command = command.replace('VAR2', whatever2)
    # ...
    return command
hooks = {'Command': transform_command}

You can then assign those variables in my_script.sh by simply calling:

export VAR1=$1
export VAR2=$2
export VAR3=$3

...then you can call whatever you normally would (say, ssh_connect.py or your own ssh command).

For host-initiated callbacks you'd use the "special optional escape sequence handler" (aka SOESH). There's an example of how that works in the example plugin but the 'notice' plugin is good too. Here's the entire notice.py plugin:

# Special optional escape sequence handler (see docs on how it works)
def notice_esc_seq_handler(self, message):
    """
    Handles text passed from the special optional escape sequance handler to
    display a *message* to the connected client (browser).

    .. seealso:: :class:`gateone.TerminalWebSocket.esc_opt_handler` and :func:`terminal.Terminal._opt_handler`
    """
    message = {'go:notice': message}
    self.write_message(message)

hooks = {
    'Escape': notice_esc_seq_handler,
}

Here's how it works:

Your plugin can do whatever it likes with the message. Here's an idea for you:

print(`\x1b]_;myplugin|exec_callback:foo:"arg1","arg2","arg3"\x07`)

Call that form the application at the endpoint and Gate One will send exec_callback:foo:"arg1","arg2","arg3" to your escape sequence handler function. Which you can then do something like command = message.split(':', 1) and parse out the callback and arguments as you see fit. So on and so forth.

Hopefully that answers your questions. Note that Gate One's termio.py module has extensive shell automation capabilities (expect), can perform screen scraping, and you can use it from within Gate One plugins (see ssh.py).