Add basic builder code

- Takes in config via traitlets
- Pushes image after it is built
- Can run different detectors easily as well
- Single straight up application that runs from start to end,
  no concurrency (woot!)
pull/2/head
yuvipanda 2017-05-09 01:37:19 -07:00
rodzic 8ddf7704ce
commit aa7eb895c1
2 zmienionych plików z 140 dodań i 0 usunięć

89
builder/app.py 100644
Wyświetl plik

@ -0,0 +1,89 @@
import json
import os
from traitlets.config import Application, LoggingConfigurable, Unicode, Dict, List
from traitlets import Type
import docker
import subprocess
from .detectors import BuildPack, PythonBuildPack
class Builder(Application):
config_file = Unicode(
'builder_config.py',
config=True
)
build_name = Unicode(
None,
allow_none=True,
config=True
)
source_url = Unicode(
None,
allow_none=True,
config=True
)
output_image_spec = Unicode(
None,
allow_none=True,
config=True
)
git_workdir = Unicode(
"/tmp/git",
config=True
)
buildpacks = List(
None,
[PythonBuildPack],
config=True
)
aliases = Dict({
'source': 'Builder.source_url',
'output': 'Builder.output_image_spec',
'f': 'Builder.config_file',
'n': 'Builder.build_name'
})
def fetch(self, url, ref, output_path):
subprocess.check_call([
"git", "clone", "--depth", "1",
url, output_path
])
def initialize(self, *args, **kwargs):
super().initialize(*args, **kwargs)
self.load_config_file(self.config_file)
def run(self):
output_path = os.path.join(self.git_workdir, self.build_name)
self.fetch(
self.source_url,
'master',
output_path
)
for bp_class in self.buildpacks:
bp = bp_class()
if bp.detect(output_path):
bp.build(output_path, self.output_image_spec)
client = docker.from_env(version='1.24')
for line in client.images.push(self.output_image_spec, stream=True):
progress = json.loads(line.decode('utf-8'))
print(progress['status'])
if __name__ == '__main__':
f = Builder()
f.initialize()
f.run()

Wyświetl plik

@ -0,0 +1,51 @@
import os
import subprocess
from traitlets import Unicode, Dict
from traitlets.config import LoggingConfigurable
class BuildPack(LoggingConfigurable):
def detect(self, workdir):
"""
Return True if app in workdir can be built with this buildpack
"""
pass
def build(self, workdir, output_image_spec):
"""
Run a command that will take workdir and produce an image ready to be pushed
"""
pass
class PythonBuildPack(BuildPack):
runtime_builder_map = Dict({
'python-2.7': 'jupyterhub/singleuser-builder-venv-2.7:v0.1.2',
'python-3.5': 'jupyterhub/singleuser-builder-venv-3.5:v0.1.2',
})
runtime = Unicode(
'python-3.5',
config=True
)
def detect(self, workdir):
if os.path.exists(os.path.join(workdir, 'requirements.txt')):
try:
with open(os.path.join(workdir, 'runtime.txt')) as f:
self.runtime = f.read().strip()
except FileNotFoundError:
pass
return True
def build(self, workdir, output_image_spec):
cmd = [
's2i',
'build',
workdir,
self.runtime_builder_map[self.runtime],
output_image_spec
]
subprocess.check_call(cmd)