Permalink
Browse files

working proxy in container

  • Loading branch information...
1 parent 06b7d8f commit a7972270a43512f4e0c8e336c25f068c1c162db3 @astiunov astiunov committed Mar 24, 2017
Showing with 79 additions and 56 deletions.
  1. +0 −3 etc/local_config.py
  2. +2 −10 etc/nginx_config.conf
  3. +43 −22 everware/container_handler.py
  4. +14 −4 everware/git_processor.py
  5. +20 −17 everware/spawner.py
View
@@ -4,6 +4,3 @@
c = get_config()
load_subconfig('etc/base_config.py')
load_subconfig('etc/github_auth.py')
-
-# c.Spawner.custom_service_url = 'git'
-# c.Spawner.custom_service_name = 'Git UI'
View
@@ -21,20 +21,12 @@ http {
location / {
proxy_pass http://custom_service;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Host $server_name;
+ proxy_set_header Host localhost:8080;
}
location /service/%USERNAME%/ {
proxy_pass http://custom_service/;
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Host $server_name;
+ proxy_set_header Host localhost:8080;
}
}
@@ -1,12 +1,12 @@
from dockerspawner import DockerSpawner
from tornado import gen
-import sys
+import re
class ContainerHandler(DockerSpawner):
@gen.coroutine
- def prepare_container(self, everware_based, need_service):
- self.debug_log = open('debug_log', 'w')
+ def prepare_container(self, need_service):
container = yield self.get_container()
+ everware_based = yield self._is_everware_compatible(container)
if not everware_based or need_service:
yield self._init_container(container, everware_based)
if need_service:
@@ -22,13 +22,11 @@ def prepare_container(self, everware_based, need_service):
if git_webui_started:
self.log.info('git webui has started in %s' % self.container_id)
self._add_to_log('Git Web UI has started')
+ else:
+ self.log.info('failed to start nginx in %s' % self.container_id)
if not git_webui_started:
self._add_to_log('Failed to start git web ui')
-
- if everware_based:
- return
-
- yield self._run_all(container)
+ self.user_options['custom_service'] = False
def _encode_conf(self, s):
return ''.join('\\x' + hex(ord(x))[2:].zfill(2) for x in s)
@@ -50,30 +48,33 @@ def _start_nginx(self, container, token, username):
"service nginx restart && cat /etc/nginx/nginx.conf\""
)
output = yield self.docker('exec_start', exec_id=setup['Id'])
- print(output, file=self.debug_log)
+ # print(output, file=self.debug_log)
+ # print(str(output), file=sys.stderr)
+ return re.search(
+ r'Restarting nginx.+?\.\.\.done\.',
+ str(output),
+ flags=re.DOTALL
+ )
except OSError:
self.log.info('No nginx config')
return False
- return True
@gen.coroutine
def _start_service(self, container):
setup = yield self.docker(
'exec_create',
container=container,
cmd="bash -c '"+\
- "curl https://raw.githubusercontent.com/alberthier/git-webui/master/install/installer.sh >installer.sh" +\
- " && bash installer.sh && cd {} && git webui --port=8081 --host=0.0.0.0 --no-browser >/dev/null 2>/dev/null &'".format(
- '/notebooks'
- )
+ "curl https://raw.githubusercontent.com/everware/git-webui/master/install/installer.sh >installer.sh" +\
+ " && bash installer.sh && cd /notebooks; "+\
+ "git webui --port=8081 --host=0.0.0.0 --no-browser >/dev/null 2>&1 &'"
)
output = yield self.docker('exec_start', exec_id=setup['Id'])
- print(output, file=sys.stderr)
return True
@gen.coroutine
def _init_container(self, container, everware_based):
- cmd = "bash -c 'apt-get update && apt-get install git wget curl -y"
+ cmd = "bash -c 'apt-get update && apt-get install git curl net-tools -y"
if everware_based:
cmd += "'"
else:
@@ -91,16 +92,36 @@ def _init_container(self, container, everware_based):
cmd=cmd
)
output = yield self.docker('exec_start', exec_id=setup['Id'])
- print(output, file=self.debug_log)
+
+ #@gen.coroutine
+ #def _run_jupyter(self, container):
+ # setup = yield self.docker(
+ # 'exec_create',
+ # container=container,
+ # cmd="bash -c 'apt-get install jupyter -y && "+\
+ # "curl https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/jupyterhub/singleuser.py >singleuser.py" +\
+ # " && chmod +x singleuser.py && ./singleuser.py --port=8888 --ip=0.0.0.0 --no-browser &'"
+ # )
+ # output = yield self.docker('exec_start', exec_id=setup['Id'])
+ # print(output, file=self.debug_log)
@gen.coroutine
- def _run_all(self, container):
+ def _is_everware_compatible(self, container):
setup = yield self.docker(
'exec_create',
container=container,
- cmd="bash -c 'apt-get install jupyter -y && "+\
- "curl https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/jupyterhub/singleuser.py >singleuser.py" +\
- " && chmod +x singleuser.py && ./singleuser.py --port=8888 --ip=0.0.0.0 --no-browser &'"
+ cmd="bash -c \"ls / | grep -E '\\bnotebooks\\b'\""
)
output = yield self.docker('exec_start', exec_id=setup['Id'])
- print(output, file=self.debug_log)
+ return output != ""
+
+ #@gen.coroutine
+ #def _is_jupyter_inside(self, container):
+ # setup = yield self.docker(
+ # 'exec_create',
+ # container=container,
+ # cmd="bash -c 'netstat -peant | grep \":8888 \"'"
+ # )
+ # output = yield self.docker('exec_start', exec_id=setup['Id'])
+ # print('jupyter check:', output, file=sys.stderr)
+ # return output != ""
View
@@ -107,17 +107,27 @@ def prepare_local_repo(self):
dockerfile_path = os.path.join(self._repo_dir, 'Dockerfile')
if not os.path.isfile(dockerfile_path):
- if not os.environ.get('DEFAULT_DOCKER_IMAGE'):
+ if self.config_files_exist():
+ parent_image = 'everware/base:latest'
+ elif not os.environ.get('DEFAULT_DOCKER_IMAGE'):
raise Exception('No dockerfile in repository')
+ else:
+ parent_image = os.environ['DEFAULT_DOCKER_IMAGE']
with open(dockerfile_path, 'w') as fout:
fout.writelines([
- 'FROM %s\n' % os.environ['DEFAULT_DOCKER_IMAGE'],
- 'MAINTAINER Alexander Tiunov <astiunov@yandex-team.ru>'
+ 'FROM %s\n' % parent_image
])
return False
else:
return True
+ def config_files_exist(self):
+ # uncomment when this functionality will be implemented
+ # for conf in ('everware.yml', 'requirements.txt', 'environment.yml'):
+ # cur_path = os.path.join(self._repo_dir, conf)
+ # if os.path.isfile(cur_path):
+ # return True
+ return False
@property
def escaped_repo_url(self):
@@ -183,4 +193,4 @@ def get_state(self):
def load_state(self, state):
for key in self.STATE_VARS:
if key in state:
- setattr(self, key, state[key])
+ setattr(self, key, state[key])
View
@@ -140,14 +140,6 @@ def _options_form_default(self):
checked />
<span class="mdl-checkbox__label">Remove previous container if it exists</span>
</label>
- <label for="everware_based" class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" >
- <input type="checkbox"
- name="everware_based"
- class="mdl-checkbox__input"
- id="everware_based"
- checked />
- <span class="mdl-checkbox__label">This repository is everware-compatible</span>
- </label>
<label for="custom_service" class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" >
<input type="checkbox"
name="custom_service"
@@ -163,10 +155,8 @@ def options_from_form(self, formdata):
options.update(formdata)
need_remove = formdata.get('need_remove', ['on'])[0].strip()
need_custom_service = formdata.get('custom_service', ['off'])[0].strip()
- compatible_repo = formdata.get('everware_based', ['on'])[0].strip()
options['need_remove'] = need_remove == 'on'
options['custom_service'] = need_custom_service == 'on'
- options['everware_based'] = compatible_repo == 'on'
if not options['repo_url']:
raise Exception('You have to provide the URL to a git repository.')
return options
@@ -259,8 +249,9 @@ def wait_up(self):
ip, port = yield self.get_ip_and_port()
self.user.server.ip = ip
self.user.server.port = port
- self.log.info('have PORT {}'.format(port))
yield self.user.server.wait_up(http=True, timeout=self.http_timeout)
+ self.user.server.ip = ip
+ self.user.server.port = port
self._is_up = True
except TimeoutError:
self._is_failed = True
@@ -319,7 +310,7 @@ def build_image(self):
'build',
path=tmp_dir,
tag=image_name,
- pull=False,
+ pull=True,
rm=True,
)
self._user_log.extend(self._cur_waiter.building_log)
@@ -405,6 +396,7 @@ def start(self, image=None):
level=2
)
yield self.notify_about_fail("Timeout limit %.3f exceeded" % self.start_timeout)
+ self._is_building = False
raise
except Exception as e:
self._is_failed = True
@@ -413,19 +405,29 @@ def start(self, image=None):
message = "Container doesn't have jupyter-singleuser inside"
self._add_to_log('Something went wrong during building. Error: %s' % message)
yield self.notify_about_fail(message)
+ self._is_building = False
raise e
+
+ try:
+ yield self.prepare_container(
+ self.need_run_custom_service()
+ )
+ except Exception as e:
+ self.log.warn('exception when preparing container: {}'.format(str(e)))
finally:
self._is_building = False
- yield self.prepare_container(
- self.user_options['everware_based'],
- self.need_run_custom_service()
- )
self._add_to_log('Adding to proxy')
yield self.wait_up()
if self.need_run_custom_service():
+ target_host = yield self.service_host()
+ self.log.info('Adding service of %s to proxy %s => %s' % (
+ self.user.name,
+ self.custom_service_path,
+ target_host
+ ))
yield self.proxy.api_request(self.custom_service_path, method='POST', body={
- 'target': self.container_proxy_host
+ 'target': target_host
})
return self.user.server.ip, self.user.server.port # jupyterhub 0.7 prefers returning ip, port
@@ -497,6 +499,7 @@ def poll(self):
if container_state["Running"]:
# check if something is listening inside container
try:
+ # self.log.info('poll {}'.format(self.user.server.url))
yield wait_for_http_server(self.user.server.url, timeout=1)
except TimeoutError:
self.log.warn("Can't reach running container by http")

0 comments on commit a797227

Please sign in to comment.