Skip to content

Commit

Permalink
Merge pull request #40 from betatim/spawner-form
Browse files Browse the repository at this point in the history
[WIP] Update to use spawner forms in jupyterhub, and @astiunov s changes
  • Loading branch information
anaderi committed Mar 4, 2016
2 parents 70e8fd6 + 328fa67 commit 79721a5
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 136 deletions.
2 changes: 0 additions & 2 deletions everware/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

from .spawner import *
from .authenticator import *
from .homehandler import *

2 changes: 1 addition & 1 deletion everware/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def get(self):
self.log.debug("Redirect with %s", state)
self.redirect(self.hub.server.base_url +'/home?'+urllib.parse.urlencode(state))
else:
self.redirect(self.hub.server.base_url)
self.redirect(self.hub.server.base_url + '/home')
else:
# todo: custom error page?
raise web.HTTPError(403)
Expand Down
38 changes: 0 additions & 38 deletions everware/homehandler.py

This file was deleted.

45 changes: 42 additions & 3 deletions everware/spawner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import re
import pwd
import zipfile
from io import BytesIO
from tempfile import mkdtemp
from datetime import timedelta
from os.path import join as pjoin

from concurrent.futures import ThreadPoolExecutor

Expand All @@ -22,6 +26,7 @@

class CustomDockerSpawner(DockerSpawner):
def __init__(self, **kwargs):
self._building = False
super(CustomDockerSpawner, self).__init__(**kwargs)

def _docker(self, method, *args, **kwargs):
Expand Down Expand Up @@ -82,16 +87,40 @@ def clear_state(self):
state = super(CustomDockerSpawner, self).clear_state()
self.container_id = ''

def _options_form_default(self):
return """
<label for="username_input">Git repository:</label>
<input
id="repository_input"
type="text"
autocapitalize="off"
autocorrect="off"
class="form-control"
name="repository_url"
tabindex="1"
autofocus="autofocus"
/>
"""

def options_from_form(self, formdata):
options = {}
options['repo_url'] = formdata.get('repository_url', [''])[0].strip()
if not options['repo_url']:
raise Exception('You have to provide the URL to a git repository.')

return options

@property
def repo_url(self):
return self.user.last_repo_url
return self.user_options['repo_url']

_escaped_repo_url = None
@property
def escaped_repo_url(self):
if self._escaped_repo_url is None:
trans = str.maketrans(':/-.', "____")
self._escaped_repo_url = self.repo_url.translate(trans)
repo_url = self.repo_url.translate(trans)
self._escaped_repo_url = re.sub("_+", "_", repo_url)
return self._escaped_repo_url

@property
Expand Down Expand Up @@ -131,6 +160,7 @@ def get_image(self, image_name):
@gen.coroutine
def start(self, image=None):
"""start the single-user server in a docker container"""
self._building = True
tic = IOLoop.current().time()

tmp_dir = mkdtemp(suffix='-everware')
Expand All @@ -154,6 +184,7 @@ def start(self, image=None):
rm=True)
self.log.debug("".join(str(line) for line in build_log))

self._building = False
# If the build took too long, do not start the container
toc = IOLoop.current().time()
if toc - tic > self.start_timeout:
Expand All @@ -163,6 +194,13 @@ def start(self, image=None):
image=image_name
)

def poll(self):
if self._building:
return None

else:
return super(CustomDockerSpawner, self).poll()

def _env_default(self):
env = super(CustomDockerSpawner, self)._env_default()

Expand Down Expand Up @@ -198,5 +236,6 @@ def start(self, image=None, extra_create_kwargs=None):
if container is not None:
node_name = container['Node']['Name']
self.user.server.ip = node_name
self.db.commit()
self.log.info("{} was started on {} ({}:{})".format(
self.container_name, node_name, self.user.server.ip, self.user.server.port))
self.container_name, node_name, self.user.server.ip, self.user.server.port))
26 changes: 12 additions & 14 deletions jupyterhub_config.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import os
import everware

import jupyterhub.handlers.pages
jupyterhub.handlers.pages.HomeHandler.get = everware.HomeHandler.get
jupyterhub.handlers.pages.HomeHandler.post = everware.HomeHandler.post

c = get_config()

# spawn with custom docker containers
#c.JupyterHub.spawner_class = 'everware.CustomDockerSpawner'
c.JupyterHub.spawner_class = 'everware.CustomSwarmSpawner'
c.JupyterHub.spawner_class = 'everware.CustomDockerSpawner'
#c.JupyterHub.spawner_class = 'everware.CustomSwarmSpawner'

# The docker instances need access to the Hub, so the default loopback port doesn't work:
# Find it easier to hardcode the IP of the machine it is deployed on
#from IPython.utils.localinterfaces import public_ips
c.JupyterHub.hub_ip = '128.142.143.186'#public_ips()[0]
c.JupyterHub.hub_api_ip = '128.142.143.186'#public_ips()[0]
ip_addr = '192.168.99.1'
c.JupyterHub.hub_ip = ip_addr
c.JupyterHub.hub_api_ip = ip_addr

c.JupyterHub.authenticator_class = 'everware.GitHubOAuthenticator'
c.JupyterHub.authenticator_class = 'oauthenticator.GitHubOAuthenticator'
c.Authenticator.whitelist = set(['betatim', 'ibab', 'kdungs', 'seneubert', 'alexpearce'])

c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
Expand All @@ -33,9 +30,10 @@
c.Spawner.tls_assert_hostname = False
c.Spawner.use_docker_client_env = True

c.JupyterHub.data_files_path = 'share'
c.JupyterHub.template_paths = ['share/static/html']
#c.JupyterHub.data_files_path = 'share'
#c.JupyterHub.template_paths = ['share/static/html']

# change this to the ip that `boot2docker ip` tells you if
# you use boot2docker, otherwise remove the line
#c.Spawner.container_ip = '192.168.59.103'
# change this to the ip that `boot2docker ip` or
# `docker-machine ip <vm_name>`tells you if
# you use boot2docker/a VM, otherwise remove the line
c.Spawner.container_ip = '192.168.99.100'
99 changes: 21 additions & 78 deletions share/static/html/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,92 +2,35 @@

{% block main %}

<div id="login-main">
<header class="jumbotron masthead">
<h1>everware</h1>
<p>Sharing is caring</p>
</header>

<form class="form-horizontal" action="/hub/home" method="post" role="form" id="repo_url_entry">
<div id="form_div">
<div class="form-group" id="repourl_div">
<input
type="text"
class="form-control"
name="repourl"
id="repo_input"
tabindex="1"
placeholder="URL of git repository"
{% if repo_url %}
value="{{repo_url}}"
{% endif %}
/>
</div>
<input
type="submit"
id="login_submit"
class='btn btn-lg btn-primary btn-block'
value='Launch'
tabindex="4"
/>
</div>
</form>

<div class="container">
<div class="row row-centered">
<div class="col-sm-6" style="float:none; margin:0 auto">
Paste the link to the git repository you want to try out. If you
need some inspiration try one of the following repositories:
<ul>
<li>https://github.com/everware/everware-dimuon-example</li>
<li>https://github.com/betatim/everware-demo</li>
</ul>
Read the documentation
to <a href="https://github.com/everware/everware/wiki/Being-everware-compatible">learn
how to make your repositories work</a> with everware.
<div class="row">
<div class="text-center">
{% if user.running %}
<a id="stop" class="btn btn-lg btn-danger">Stop My Server</a>
{% endif %}
<a id="start" class="btn btn-lg btn-success"
{% if user.running %}
href="{{base_url}}user/{{user.name}}/"
{% else %}
href="{{base_url}}spawn"
{% endif %}
>
{% if not user.running %}
Start
{% endif %}
My Server
</a>
{% if user.admin %}
<a id="admin" class="btn btn-lg btn-primary" href="{{base_url}}admin">Admin</a>
{% endif %}
</div>
</div>
</div>

<footer class="footer">
<div class="footer-inside">
<div class="col-sm-8">
Powered by <a href="https://jupyter.org/">Jupyter</a> and <a href="https://www.docker.com/">Docker</a>
</div>
<div style="float: right;">Logged in as {{user.name}} (<a id="logout" href="{{logout_url}}">Logout</a>)</div>
</div>
</footer>

{% endblock %}

{% block script %}
<script type="text/javascript">
require(["home"]);

function replaceRepoURL(e) {
var target = e.target || e.srcElement
var repo_url = target.repo_input.value;

if (repo_url.startsWith('git@')) {
e.preventDefault();

repo_url = repo_url.replace(':', '/').replace('git@', 'https://');
target.repo_input.value = repo_url;

var msg = document.createElement("div");
msg.innerText = "We changed the repository's URL for you.";
var form_div = document.getElementById('form_div');
console.log(form_div);
form_div.insertBefore(msg, document.getElementById("repourl_div"));
}
}

var form = document.getElementById('repo_url_entry');
if (form.attachEvent) {
form.attachEvent("submit", replaceRepoURL);
} else {
form.addEventListener("submit", replaceRepoURL);
}

require(["home"]);
</script>
{% endblock %}

0 comments on commit 79721a5

Please sign in to comment.