Skip to content

Commit

Permalink
Fix logging statements and command name
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukasz Stempniewicz committed May 2, 2018
1 parent 4e748f2 commit 974b01b
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 78 deletions.
6 changes: 3 additions & 3 deletions src/webapp/azext_webapp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, cli_ctx=None):
def load_command_table(self, _):
with self.command_group('webapp') as g:
g.custom_command('up', 'create_deploy_webapp')
g.custom_command('tunnel create','create_tunnel')
g.custom_command('remote-connection create', 'create_tunnel')
g.custom_command('config snapshot list', 'list_webapp_snapshots')
g.custom_command('config snapshot restore', 'restore_webapp_snapshot')
return self.command_table
Expand All @@ -34,8 +34,8 @@ def load_arguments(self, _):
c.argument('dryrun',
help="shows summary of the create and deploy operation instead of executing it",
default=False, action='store_true')
with self.argument_contect('webapp tunnel create') as c:
c.argument('port',options_list=['--port', '-p'], help='Port for the remote connection', type=int)
with self.argument_context('webapp remote-connection create') as c:
c.argument('port', options_list=['--port', '-p'], help='Port for the remote connection', type=int)
with self.argument_context('webapp config snapshot list') as c:
c.argument('resource_group', options_list=['--resource-group', '-g'], help='Name of resource group.')
c.argument('name', options_list=['--webapp-name', '-n'], help='Name of the webapp.')
Expand Down
5 changes: 3 additions & 2 deletions src/webapp/azext_webapp/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
az webapp up -n MyUniqueAppName --dryrun \n
az webapp up -n MyUniqueAppName -l locationName
"""
helps['webapp tunnel'] = """
helps['webapp remote-connection'] = """
type: group
short-summary: Create a remote connection using a tcp tunnel to your app
"""

helps['webapp tunnel create'] = """
helps['webapp remote-connection create'] = """
type: command
short-summary: Create a remote connection using a tcp tunnel to your app
"""

helps['webapp config snapshot list'] = """
type: command
Expand Down
67 changes: 35 additions & 32 deletions src/webapp/azext_webapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,38 +184,6 @@ def create_deploy_webapp(cmd, name, location=None, dryrun=False):
logger.warning("All done.")
return create_json

def _check_for_ready_tunnel(cmd, resource_group_name, name, remote_debugging, tunnel_server, slot=None):
from .tunnel import TunnelServer
default_port = tunnel_server.is_port_set_to_default()
if default_port is not remote_debugging:
return True
return False

def create_tunnel(cmd, resource_group_name, name, port, slot=None):
profiles = list_publish_profiles(cmd, resource_group_name, name, slot)
user_name = next(p['userName'] for p in profiles)
user_password = next(p['userPWD'] for p in profiles)
import time
import threading
from .tunnel import TunnelServer
tunnel_server = TunnelServer('', port, name, user_name, user_password)

config = get_site_configs(cmd, resource_group_name, name, slot)

if not _check_for_ready_tunnel(cmd, resource_group_name, name, config.remote_debugging_enabled, tunnel_server, slot):
print('Tunnel is not ready yet, please wait (may take up to 1 minute)')

t = threading.Thread()
t.daemon = True
t.start()

while True:
time.sleep(1)
print('.')
if _check_for_ready_tunnel(cmd, resource_group_name, name, config.remote_debugging_enabled, slot):
break
print('Tunnel is ready! Creating on port {}'.format(port))
tunnel_server.start_server()

def list_webapp_snapshots(cmd, resource_group, name, slot=None):
client = web_client_factory(cmd.cli_ctx)
Expand Down Expand Up @@ -247,3 +215,38 @@ def restore_webapp_snapshot(cmd, resource_group, name, time, slot=None, restore_
return client.web_apps.recover_slot(resource_group, name, request, slot)
else:
return client.web_apps.recover(resource_group, name, request)


def _check_for_ready_tunnel(cmd, resource_group_name, name, remote_debugging, tunnel_server, slot=None):
from .tunnel import TunnelServer
default_port = tunnel_server.is_port_set_to_default()
if default_port is not remote_debugging:
return True
return False


def create_tunnel(cmd, resource_group_name, name, port, slot=None):
profiles = list_publish_profiles(cmd, resource_group_name, name, slot)
user_name = next(p['userName'] for p in profiles)
user_password = next(p['userPWD'] for p in profiles)
import time
import threading
from .tunnel import TunnelServer
tunnel_server = TunnelServer('', port, name, user_name, user_password)

config = get_site_configs(cmd, resource_group_name, name, slot)

if not _check_for_ready_tunnel(cmd, resource_group_name, name, config.remote_debugging_enabled, tunnel_server, slot):
print('Tunnel is not ready yet, please wait (may take up to 1 minute)')

t = threading.Thread()
t.daemon = True
t.start()

while True:
time.sleep(1)
print('.')
if _check_for_ready_tunnel(cmd, resource_group_name, name, config.remote_debugging_enabled, slot):
break
print('Tunnel is ready! Creating on port {}'.format(port))
tunnel_server.start_server()
84 changes: 44 additions & 40 deletions src/webapp/azext_webapp/tunnel.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import sys
import ssl
import socket
Expand All @@ -11,22 +16,24 @@

from knack.util import CLIError
from knack.log import get_logger
logger = get_logger(__name__) # TODO: Replace print with logger below
logger = get_logger(__name__)


class TunnelWebSocket(WebSocket):
def recv_frame(self):
frame = super(TunnelWebSocket, self).recv_frame()
print('Received frame:{}'.format(frame))
logger.info('Received frame: %s', frame)
return frame

def recv(self):
data = super(TunnelWebSocket, self).recv()
print('Received websocket data:{}'.format(data))
logger.info('Received websocket data: %s', data)
return data

def send_binary(self, data):
super(TunnelWebSocket, self).send_binary(data)


class TunnelServer(object):
def __init__(self, local_addr, local_port, remote_addr, remote_user_name, remote_password):
self.local_addr = local_addr
Expand All @@ -36,13 +43,13 @@ def __init__(self, local_addr, local_port, remote_addr, remote_user_name, remote
self.remote_addr = remote_addr
self.remote_user_name = remote_user_name
self.remote_password = remote_password
print('Creating a socket')
logger.info('Creating a socket on port: %s', self.local_port)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Setting socket options')
logger.info('Setting socket options')
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print('Binding to socket on local address and port')
logger.info('Binding to socket on local address and port')
self.sock.bind((self.local_addr, self.local_port))
print('Got to the end of init')
logger.info('Finished initialization')

def create_basic_auth(self):
from base64 import b64encode, b64decode
Expand All @@ -54,12 +61,12 @@ def is_port_open(self):
is_port_open = False
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
if sock.connect_ex(('', self.local_port)) == 0:
print('Port is open')
logger.info('Port %s is open', self.local_port)
is_port_open = True
else:
print('Port is not open')
logger.warning('Port %s is NOT open', self.local_port)
return is_port_open

def is_port_set_to_default(self):
import sys
import certifi
Expand All @@ -69,10 +76,10 @@ def is_port_set_to_default(self):
urllib3.contrib.pyopenssl.inject_into_urllib3()
except ImportError:
pass

http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(self.remote_user_name, self.remote_password))
url = 'https://{}{}'.format(self.remote_addr,'.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx?GetStatus')
url = 'https://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx?GetStatus')
r = http.request(
'GET',
url,
Expand All @@ -84,54 +91,52 @@ def is_port_set_to_default(self):
if '2222' in r.text:
return True
return False



def listen(self):
self.sock.listen(100)
index = 0
basic_auth_string = self.create_basic_auth()
while True:
self.client, address = self.sock.accept()
self.client.settimeout(60)
host = 'wss://{}{}'.format(self.remote_addr,'.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx')
host = 'wss://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx')
basic_auth_header = 'Authorization: Basic {}'.format(basic_auth_string)
websocket.enableTrace(True)
self.ws = create_connection(host,
sockopt = ((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),),
class_ = TunnelWebSocket,
header = [basic_auth_header],
sslopt={'cert_reqs': ssl.CERT_NONE},
sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),),
class_=TunnelWebSocket,
header=[basic_auth_header],
sslopt={'cert_reqs': ssl.CERT_NONE},
enable_multithread=True)
print('websocket, connected status:{}', self.ws.connected)
logger.info('Websocket, connected status: %s', self.ws.connected)

index = index + 1
print('got debugger connection... index:{}'.format(index))
debugger_thread = Thread(target = self.listen_to_client, args = (self.client, self.ws, index))
web_socket_thread = Thread(target = self.listen_to_web_socket, args = (self.client, self.ws, index))
logger.info('Got debugger connection... index: %s', index)
debugger_thread = Thread(target=self.listen_to_client, args=(self.client, self.ws, index))
web_socket_thread = Thread(target=self.listen_to_web_socket, args=(self.client, self.ws, index))
debugger_thread.start()
web_socket_thread.start()
print('both threads started...')
logger.info('Both debugger and websocket threads started...')
debugger_thread.join()
web_socket_thread.join()
print('both threads stopped...')
logger.info('Both debugger and websocket threads stopped...')

def listen_to_web_socket(self, client, ws_socket, index):
size = 4096
while True:
try:
print('Waiting for websocket data, connection status:{}, index:{}'.format(ws_socket.connected, index))
logger.info('Waiting for websocket data, connection status: %s, index: %s', ws_socket.connected, index)
data = ws_socket.recv()
print('Received websocket data:{}, index:{}'.format(data, index))
logger.info('Received websocket data: %s, index: %s', data, index)
if data:
# Set the response to echo back the recieved data
# Set the response to echo back the recieved data
response = data
print('Sending to debugger, response:{}, index{}'.format(response, index))
logger.info('Sending to debugger, response: %s, index: %s', response, index)
client.sendall(response)
print('Done sending to debugger, index:{}', index)
logger.info('Done sending to debugger, index: %s', index)
else:
print('Client disconnected!, index:{}', index)
logger.info('Client disconnected!, index: %s', index)
client.close()
ws_socket.close()
ws_socket.close()
break
except:
traceback.print_exc(file=sys.stdout)
Expand All @@ -140,18 +145,17 @@ def listen_to_web_socket(self, client, ws_socket, index):
return False

def listen_to_client(self, client, ws_socket, index):
size = 4096
while True:
try:
print('Waiting for debugger data, index:{}'.format(index))
logger.info('Waiting for debugger data, index: %s', index)
buf = bytearray(4096)
nbytes = client.recv_into(buf, 4096)
print('Received debugger data, nbytes:{}, index:{}'.format(nbytes, index))
logger.info('Received debugger data, nbytes: %s, index: %s', nbytes, index)
if nbytes > 0:
responseData = buf[0:nbytes]
print('Sending to websocket, response data:{}, index:{}'.format(responseData, index))
logger.info('Sending to websocket, response data: %s, index: %s', responseData, index)
ws_socket.send_binary(responseData)
print('Done sending to websocket, index:{}', index)
logger.info('Done sending to websocket, index: %s', index)
else:
logger.warn('Client disconnected %s', index)
client.close()
Expand All @@ -164,4 +168,4 @@ def listen_to_client(self, client, ws_socket, index):
return False

def start_server(self):
self.listen()
self.listen()
2 changes: 1 addition & 1 deletion src/webapp/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
description='An Azure CLI Extension to manage appservice resources',
long_description='An Azure CLI Extension to manage appservice resources',
license='MIT',
author='Sisira Panchagnula',
author='Sisira Panchagnula, Lukasz Stempniewicz',
author_email='sisirap@microsoft.com',
url='https://github.com/Azure/azure-cli-extensions',
classifiers=CLASSIFIERS,
Expand Down

0 comments on commit 974b01b

Please sign in to comment.