create new composition or load existing
This commit is contained in:
parent
e262320348
commit
6eae66728b
90
composer/app/app.py
Normal file
90
composer/app/app.py
Normal file
@ -0,0 +1,90 @@
|
||||
import param
|
||||
import panel as pn
|
||||
import toml
|
||||
from .util import get_plans, get_manifest
|
||||
from .composition import Composition
|
||||
|
||||
STAGE_WELCOME = 'Welcome'
|
||||
STAGE_CONFIG_COMPOSITION = 'Configure'
|
||||
|
||||
|
||||
class Welcome(param.Parameterized):
|
||||
composition = param.Parameter()
|
||||
composition_picker = pn.widgets.FileInput(accept='.toml')
|
||||
plan_picker = param.Selector()
|
||||
ready = param.Boolean()
|
||||
|
||||
def __init__(self, **params):
|
||||
super().__init__(**params)
|
||||
self.composition_picker.param.watch(self._composition_updated, 'value')
|
||||
self.param.watch(self._plan_selected, 'plan_picker')
|
||||
self.param['plan_picker'].objects = ['Select a Plan'] + get_plans()
|
||||
|
||||
def panel(self):
|
||||
tabs = pn.Tabs(
|
||||
('New Compostion', self.param['plan_picker']),
|
||||
('Existing Composition', self.composition_picker),
|
||||
)
|
||||
|
||||
return pn.Column(
|
||||
"Either choose an existing composition or select a plan to create a new composition:",
|
||||
tabs,
|
||||
)
|
||||
|
||||
def _composition_updated(self, *args):
|
||||
print('composition updated')
|
||||
content = self.composition_picker.value.decode('utf8')
|
||||
comp_toml = toml.loads(content)
|
||||
manifest = get_manifest(comp_toml['global']['plan'])
|
||||
self.composition = Composition.from_dict(comp_toml, manifest=manifest)
|
||||
print('existing composition: {}'.format(self.composition))
|
||||
self.ready = True
|
||||
|
||||
def _plan_selected(self, evt):
|
||||
if evt.new == 'Select a Plan':
|
||||
return
|
||||
print('plan selected: {}'.format(evt.new))
|
||||
manifest = get_manifest(evt.new)
|
||||
self.composition = Composition(manifest=manifest)
|
||||
print('new composition: ', self.composition)
|
||||
self.ready = True
|
||||
|
||||
|
||||
class ConfigureComposition(param.Parameterized):
|
||||
composition = param.Parameter()
|
||||
|
||||
@param.depends('composition')
|
||||
def panel(self):
|
||||
if self.composition is None:
|
||||
return pn.Pane("no composition :(")
|
||||
print('composition: ', self.composition)
|
||||
return self.composition.panel()
|
||||
|
||||
|
||||
class WorkflowPipeline(object):
|
||||
def __init__(self):
|
||||
stages = [
|
||||
(STAGE_WELCOME, Welcome(), dict(ready_parameter='ready')),
|
||||
(STAGE_CONFIG_COMPOSITION, ConfigureComposition())
|
||||
]
|
||||
|
||||
self.pipeline = pn.pipeline.Pipeline(debug=True, stages=stages)
|
||||
|
||||
def panel(self):
|
||||
return pn.Column(
|
||||
pn.Row(
|
||||
self.pipeline.title,
|
||||
self.pipeline.network,
|
||||
self.pipeline.prev_button,
|
||||
self.pipeline.next_button,
|
||||
),
|
||||
self.pipeline.stage,
|
||||
)
|
||||
|
||||
|
||||
class App(object):
|
||||
def __init__(self):
|
||||
self.workflow = WorkflowPipeline()
|
||||
|
||||
def ui(self):
|
||||
return self.workflow.panel().servable("Testground Composer")
|
@ -1,31 +1,7 @@
|
||||
import param
|
||||
import panel as pn
|
||||
import toml
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def parse_manifest(manifest_path):
|
||||
with open(manifest_path, 'rt') as f:
|
||||
return toml.load(f)
|
||||
|
||||
|
||||
def tg_home():
|
||||
return os.environ.get('TESTGROUND_HOME',
|
||||
os.path.join(os.environ['HOME'], 'testground'))
|
||||
|
||||
|
||||
def get_plans():
|
||||
return list(os.listdir(os.path.join(tg_home(), 'plans')))
|
||||
|
||||
|
||||
def get_manifest(plan_name):
|
||||
manifest_path = os.path.join(tg_home(), 'plans', plan_name, 'manifest.toml')
|
||||
return parse_manifest(manifest_path)
|
||||
|
||||
|
||||
def print_err(*args):
|
||||
print(*args, file=sys.stderr)
|
||||
from .util import get_manifest, print_err
|
||||
|
||||
|
||||
def value_dict(parameterized, renames=None):
|
||||
@ -241,7 +217,10 @@ class Composition(param.Parameterized):
|
||||
add_group_button = pn.widgets.Button(name='Add Group')
|
||||
add_group_button.on_click(self._add_group)
|
||||
|
||||
group_panel = self.groups.panel()
|
||||
if self.groups is None:
|
||||
group_panel = pn.Column()
|
||||
else:
|
||||
group_panel = self.groups.panel()
|
||||
if self.groups_ui is None:
|
||||
self.groups_ui = pn.Column(
|
||||
add_group_button,
|
||||
|
26
composer/app/util.py
Normal file
26
composer/app/util.py
Normal file
@ -0,0 +1,26 @@
|
||||
import toml
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def parse_manifest(manifest_path):
|
||||
with open(manifest_path, 'rt') as f:
|
||||
return toml.load(f)
|
||||
|
||||
|
||||
def tg_home():
|
||||
return os.environ.get('TESTGROUND_HOME',
|
||||
os.path.join(os.environ['HOME'], 'testground'))
|
||||
|
||||
|
||||
def get_plans():
|
||||
return list(os.listdir(os.path.join(tg_home(), 'plans')))
|
||||
|
||||
|
||||
def get_manifest(plan_name):
|
||||
manifest_path = os.path.join(tg_home(), 'plans', plan_name, 'manifest.toml')
|
||||
return parse_manifest(manifest_path)
|
||||
|
||||
|
||||
def print_err(*args):
|
||||
print(*args, file=sys.stderr)
|
File diff suppressed because one or more lines are too long
@ -80,7 +80,8 @@ cleanup () {
|
||||
trap "{ cleanup; }" EXIT
|
||||
|
||||
# make sure we have the commands we need
|
||||
require_cmds jq docker
|
||||
require_cmds jq dockerimport param
|
||||
import panel as pn
|
||||
|
||||
# make temp dir for manifests
|
||||
temp_base="/tmp"
|
||||
|
Loading…
Reference in New Issue
Block a user