Skip to content

Commit 9c61ff9

Browse files
apetrescaggFTW
authored andcommitted
Automatically configure wrapper-kernel endpoints in widget (#362)
* Add pre-configured endpoints to endpoint widget automatically * Fix crash on partially-defined kernel configurations * Use LANGS_SUPPORTED constant to get list of possible kernel config sections * Rename is_default attr to implicitly_added * Adding blank line between imports and class declaration * Log failure to connect to implicitly-defined endpoints * Adding comment explaining implicitly_added * Pass auth parameter through
1 parent 2f6cc7a commit 9c61ff9

File tree

5 files changed

+42
-4
lines changed

5 files changed

+42
-4
lines changed

sparkmagic/sparkmagic/controllerwidget/magicscontrollerwidget.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,40 @@
55
from sparkmagic.controllerwidget.manageendpointwidget import ManageEndpointWidget
66
from sparkmagic.controllerwidget.managesessionwidget import ManageSessionWidget
77
from sparkmagic.controllerwidget.createsessionwidget import CreateSessionWidget
8+
from sparkmagic.livyclientlib.endpoint import Endpoint
9+
from sparkmagic.utils.constants import LANGS_SUPPORTED
10+
import sparkmagic.utils.configuration as conf
811

912

1013
class MagicsControllerWidget(AbstractMenuWidget):
1114
def __init__(self, spark_controller, ipywidget_factory, ipython_display, endpoints=None):
1215
super(MagicsControllerWidget, self).__init__(spark_controller, ipywidget_factory, ipython_display)
1316

1417
if endpoints is None:
15-
endpoints = {}
18+
endpoints = {endpoint.url: endpoint for endpoint in self._get_default_endpoints()}
1619
self.endpoints = endpoints
1720

1821
self._refresh()
1922

2023
def run(self):
2124
pass
2225

26+
@staticmethod
27+
def _get_default_endpoints():
28+
default_endpoints = set()
29+
30+
for kernel_type in LANGS_SUPPORTED:
31+
endpoint_config = getattr(conf, 'kernel_%s_credentials' % kernel_type)()
32+
if all([p in endpoint_config for p in ["url", "password", "username"]]) and endpoint_config["url"] != "":
33+
default_endpoints.add(Endpoint(
34+
username=endpoint_config["username"],
35+
password=endpoint_config["password"],
36+
auth=endpoint_config.get("auth", None),
37+
url=endpoint_config["url"],
38+
implicitly_added=True))
39+
40+
return default_endpoints
41+
2342
def _refresh(self):
2443
self.endpoints_dropdown_widget = self.ipywidget_factory.get_dropdown(
2544
description="Endpoint:",

sparkmagic/sparkmagic/controllerwidget/manageendpointwidget.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
# Copyright (c) 2015 [email protected]
22
# Distributed under the terms of the Modified BSD License.
33
from sparkmagic.controllerwidget.abstractmenuwidget import AbstractMenuWidget
4+
from sparkmagic.livyclientlib.exceptions import HttpClientException
5+
from sparkmagic.utils.sparklogger import SparkLog
46

57

68
class ManageEndpointWidget(AbstractMenuWidget):
79
def __init__(self, spark_controller, ipywidget_factory, ipython_display, endpoints, refresh_method):
810
# This is nested
911
super(ManageEndpointWidget, self).__init__(spark_controller, ipywidget_factory, ipython_display, True)
1012

13+
self.logger = SparkLog("ManageEndpointWidget")
1114
self.endpoints = endpoints
1215
self.refresh_method = refresh_method
1316

@@ -30,7 +33,14 @@ def get_existing_endpoint_widgets(self):
3033

3134
# Endpoints
3235
for url, endpoint in self.endpoints.items():
33-
endpoint_widgets.append(self.get_endpoint_widget(url, endpoint))
36+
try:
37+
endpoint_widgets.append(self.get_endpoint_widget(url, endpoint))
38+
except HttpClientException:
39+
# If we can't reach one of the default endpoints, just skip over it
40+
if not endpoint.implicitly_added:
41+
raise
42+
else:
43+
self.logger.info("Failed to connect to implicitly-defined endpoint at: %s" % url)
3444

3545
endpoint_widgets.append(self.ipywidget_factory.get_html(value="<br/>", width="600px"))
3646
else:

sparkmagic/sparkmagic/livyclientlib/endpoint.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@
22

33

44
class Endpoint(object):
5-
def __init__(self, url, auth, username="", password=""):
5+
def __init__(self, url, auth, username="", password="", implicitly_added=False):
66
if not url:
77
raise BadUserDataException(u"URL must not be empty")
88
self.url = url.rstrip(u"/")
99
self.username = username
1010
self.password = password
1111
self.auth = auth
12+
# implicitly_added is set to True only if the endpoint wasn't configured manually by the user through
13+
# a widget, but was instead implicitly defined as an endpoint to a wrapper kernel in the configuration
14+
# JSON file.
15+
self.implicitly_added = implicitly_added
1216

1317
def __eq__(self, other):
1418
if type(other) is not Endpoint:
1519
return False
1620
return self.url == other.url and self.username == other.username and self.password == other.password
1721

22+
def __hash__(self):
23+
return hash((self.url, self.username, self.password))
24+
1825
def __ne__(self, other):
1926
return not self == other
2027

sparkmagic/sparkmagic/livyclientlib/linearretrypolicy.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ def __init__(self, seconds_to_sleep, max_retries):
1111
self._max_retries = max_retries
1212

1313
def should_retry(self, status_code, error, retry_count):
14+
if None in (status_code, retry_count):
15+
return False
1416
return (status_code >= 500 and retry_count <= self._max_retries) or error
1517

1618
def seconds_to_sleep(self, retry_count):

sparkmagic/sparkmagic/utils/configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def server_extension_default_kernel_name():
220220
def _credentials_override(f):
221221
"""Provides special handling for credentials. It still calls _override().
222222
If 'base64_password' in config is set, it will base64 decode it and returned in return value's 'password' field.
223-
If 'base64_password' is not set, it will fallback to to 'password' in config.
223+
If 'base64_password' is not set, it will fallback to 'password' in config.
224224
"""
225225
credentials = f()
226226
base64_decoded_credentials = {k: credentials.get(k) for k in ('username', 'password', 'url', 'auth')}

0 commit comments

Comments
 (0)