2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-22 09:32:21 +00:00

Flesh out the confetty interactive console slightly

This commit is contained in:
Jarrod Johnson 2014-02-09 17:35:49 -05:00
parent 51229d8185
commit abab0e5cae
3 changed files with 110 additions and 9 deletions

View File

@ -29,12 +29,14 @@ import getpass
import optparse
import os
import select
import shlex
import socket
import ssl
import sys
import termios
import tty
target = "/"
path = os.path.dirname(os.path.realpath(__file__))
path = os.path.realpath(os.path.join(path, '..'))
sys.path.append(path)
@ -47,6 +49,10 @@ conserversequence = '\x05c' # ctrl-e, c
oldtcattr = termios.tcgetattr(sys.stdin.fileno())
server = None
def prompt():
sys.stdout.write(target + ' -> ')
sys.stdout.flush()
def parseservervalue(serverstring):
if serverstring.find(']:') != -1:
server, port = serverstring[1:].split(']:')
@ -61,6 +67,62 @@ def parseservervalue(serverstring):
return (server, port)
def parse_command(command):
args = shlex.split(command, posix=True)
return args
def do_command(command, server):
global target
if command == "": # result of ctrl-d
command = "exit\n"
print("exit")
command = command[:-1]
command = command.lower()
argv = parse_command(command)
if len(argv) == 0:
prompt()
return
if argv[0] == "exit":
server.close()
sys.exit(0)
if argv[0] == "cd":
otarget = target
change_target(argv[1])
tlvdata.send_tlvdata(server, {"operation": 'retrieve', 'path': target})
result = tlvdata.recv_tlvdata(server)
if 'error' in result:
print target + ':' + result['error']
target = otarget
prompt()
def change_target(path):
global target
pathcomponents = path.split("/")
if pathcomponents[0] == "": # absolute path
target = path
else:
targparts = target.split("/")[:-1]
for component in pathcomponents:
if component in ('.',''): # ignore these
continue
elif component == '..':
if len(targparts) > 0:
del targparts[-1]
else:
targparts.append(component)
targparts.append('')
target = '/'.join(targparts)
if len(target) ==0 or target[-1] != '/':
target += '/'
def startconsole():
tty.setraw(sys.stdin.fileno())
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
def exit(code=0):
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, oldtcattr)
server.shutdown(socket.SHUT_RDWR)
@ -151,13 +213,15 @@ while authinfo['authpassed'] != 1:
tlvdata.send_tlvdata(server,
{'username': username, 'passphrase': passphrase})
authinfo = tlvdata.recv_tlvdata(server)
tty.setraw(sys.stdin.fileno())
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
# clear on start can help with readable of TUI, but it
# can be annoying, so for now don't do it.
# sys.stdout.write('\x1b[H\x1b[J')
# sys.stdout.flush()
doexit = False
inconsole = False
pendingcommand = ""
prompt()
while not doexit:
rdylist, _, _ = select.select((sys.stdin, server), (), (), 60)
for fh in rdylist:
@ -175,8 +239,13 @@ while not doexit:
sys.stdout.write("\r\n[remote disconnected]\r\n")
break
else:
input = fh.read()
input = check_escape_seq(input, fh)
if input:
tlvdata.send_tlvdata(server, input)
if inconsole:
input = fh.read()
input = check_escape_seq(input, fh)
if input:
tlvdata.send_tlvdata(server, input)
else:
command = fh.readline()
inconsole = do_command(command, server)
exit()

View File

@ -91,7 +91,7 @@ class ConfluentChoiceMessage(ConfluentMessage):
class LinkRelation(ConfluentMessage):
def json_hal(self):
def json(self):
"""Provide json_hal style representation of the relation.
This currently only makes sense for the socket api.

View File

@ -9,9 +9,13 @@ import confluent.auth as auth
import confluent.common.tlvdata as tlvdata
import confluent.consoleserver as consoleserver
import confluent.config.configmanager as configmanager
import confluent.exceptions as exc
import confluent.messages
import confluent.pluginapi as pluginapi
import eventlet.green.socket as socket
import eventlet.green.ssl as ssl
import eventlet
import json
import os
import struct
@ -19,7 +23,7 @@ SO_PEERCRED = 17
class ClientConsole(object):
def __init__(self, client):
self.client = client
self.client = clientn
def sendall(self, data):
tlvdata.send_tlvdata(self.client, data)
@ -41,7 +45,7 @@ def sessionhdl(connection, authname):
response = tlvdata.recv_tlvdata(connection)
username = response['username']
passphrase = response['passphrase']
# NOTE(jbjohnso): Here, we need to authenticate, but not
# note(jbjohnso): here, we need to authenticate, but not
# authorize a user. When authorization starts understanding
# element path, that authorization will need to be called
# per request the user makes
@ -50,6 +54,34 @@ def sessionhdl(connection, authname):
authenticated = True
cfm = authdata[1]
tlvdata.send_tlvdata(connection, {'authpassed': 1})
request = tlvdata.recv_tlvdata(connection)
while request is not None:
process_request(connection, request, cfm, authdata)
request = tlvdata.recv_tlvdata(connection)
def send_response(responses, connection):
for rsp in responses:
tlvdata.send_tlvdata(connection, json.dumps(rsp.json()))
def process_request(connection, request, cfm, authdata):
#TODO(jbjohnso): authorize each request
if type(request) == dict:
operation = request['operation']
path = request['path']
params = request.get('parameters', None)
try:
hdlr = pluginapi.handle_path(path, operation, cfm, params)
except exc.NotFoundException:
tlvdata.send_tlvdata(connection, {"errorcode": 404,
"error": "Target not found"})
return
except exc.InvalidArgumentException:
tlvdata.send_tlvdata(connection, {"errorcode": 400,
"error": "Bad Request"})
return
send_response(hdlr, connection)
return
ccons = ClientConsole(connection)
consession = consoleserver.ConsoleSession(node='n4', configmanager=cfm,
datacallback=ccons.sendall)