Add support for provisioning and rebuilding via interface

This commit is contained in:
Tom 2023-07-09 11:18:14 +02:00
parent f5c5999f44
commit ddb4bb3546
76 changed files with 1306 additions and 625 deletions

View file

@ -75,6 +75,7 @@ var (
menuInstances = component.MenuItem{Title: "Instances", Path: "/admin/instances/"}
menuInstance = component.DummyMenuItem()
menuRebuild = component.DummyMenuItem()
menuGrants = component.DummyMenuItem()
menuIngredients = component.DummyMenuItem()
)
@ -146,6 +147,11 @@ func (admin *Admin) HandleRoute(ctx context.Context, route string) (handler http
router.Handler(http.MethodGet, route+"instance/:slug", instance)
}
{
rebuild := admin.instanceRebuild(ctx)
router.Handler(http.MethodGet, route+"rebuild/:slug", rebuild)
}
{
grants := admin.grants(ctx)
router.Handler(http.MethodGet, route+"grants/:slug", grants)

View file

@ -139,7 +139,7 @@ func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (funcs
// replace the functions
funcs = []templating.FlagFunc{
templating.ReplaceCrumb(menuInstance, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
templating.ReplaceCrumb(menuGrants, component.MenuItem{Title: "Grants", Path: template.URL("/admin/instance/" + slug + "/grants/")}),
templating.ReplaceCrumb(menuGrants, component.MenuItem{Title: "Grants", Path: template.URL("/admin/grants/" + slug)}),
templating.Title(gc.Instance.Slug + " - Grants"),
}
return funcs, nil

View file

@ -84,6 +84,48 @@
</div>
</div>
</div>
<div class="pure-u-1 pure-u-xl-2-5">
<div class="padding">
<div class="overflow">
<table class="pure-table pure-table-bordered">
<thead>
<tr>
<th colspan="2">
System
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
PHP Version
</td>
<td>
<code>{{ .Instance.System.PHP }}</code>
</td>
</tr>
<tr>
<td>
Docker Base Image
</td>
<td>
<code>{{ .Instance.System.GetDockerBaseImage }}</code>
</td>
</tr>
<tr>
<td>
OPCache Development Config
</td>
<td>
<code>{{ .Instance.System.OpCacheDevelopment }}</code>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="pure-u-1 pure-u-xl-2-5">
<div class="padding">
<div class="overflow">
@ -182,7 +224,7 @@
<tr>
<td>
Last Rebuild <br>
<button class="remote-action pure-button pure-button-action" data-action="rebuild" data-param="{{ .Instance.Slug }}" data-buffer="1000" data-force-reload>Rebuild</button>
<a class="pure-button" href="/admin/rebuild/{{ .Info.Slug }}">Rebuild</button>
</td>
<td>
<code class="date">{{ .Info.LastRebuild.Format "2006-01-02T15:04:05Z07:00" }}</code>

View file

@ -1,11 +1,38 @@
<div class="pure-u-1-1">
<form class="pure-form pure-form-aligned" id="provision">
<fieldset disabled="disabled">
<fieldset>
<legend>Main Parameters</legend>
<div class="pure-control-group">
<label for="slug">Slug</label>
<input name="slug" id="slug" placeholder="" autocomplete="slug">
</div>
<input type="submit" value="Provision" class="pure-button">
</fieldset>
<fieldset>
<legend>System Parameters</legend>
<div class="pure-control-group">
<label for="php">PHP Version</label>
<select id="php">
<option value="" selected>Default ({{ .DefaultPHPVersion }})</option>
{{ range .PHPVersions }}
<option value="{{ . }}">{{ . }}</option>
{{ end }}
</select>
</div>
<label for="opcacheDevelopment" class="pure-checkbox">
<input type="checkbox" id="opcacheDevelopment" />
Opache Development Configuration
</label>
</fieldset>
<fieldset>
<legend>Profile</legend>
<div class="pure-control-group">
Not yet available
</div>
</fieldset>
<input type="submit" value="Provision" class="pure-button">
</form>
</div>

View file

@ -0,0 +1,39 @@
<div class="pure-u-1-1">
<form class="pure-form pure-form-aligned" id="provision">
<fieldset>
<legend>Main Parameters</legend>
<div class="pure-control-group">
<label for="slug">Slug</label>
<input name="slug" id="slug" placeholder="" autocomplete="slug" readonly="readonly" value="{{ .Slug }}">
</div>
</fieldset>
<fieldset>
<legend>System Parameters</legend>
<div class="pure-control-group">
<label for="php">PHP Version</label>
<select id="php">
{{ $PHP := .System.PHP }}
<option {{ if eq $PHP "" }}selected{{ end }}>Default ({{ .DefaultPHPVersion }})</option>
{{ range .PHPVersions }}
<option {{ if eq $PHP . }}selected{{ end }} value="{{ . }}">{{ . }}</option>
{{ end }}
</select>
</div>
<label for="opcacheDevelopment" class="pure-checkbox">
<input {{ if .System.OpCacheDevelopment }}checked{{end}} type="checkbox" id="opcacheDevelopment" check/>
Opache Development Configuration
</label>
</fieldset>
<fieldset>
<legend>Profile</legend>
<div class="pure-control-group">
Not yet available
</div>
</fieldset>
<input type="submit" value="Rebuild" class="pure-button">
</form>
</div>

View file

@ -6,6 +6,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
"github.com/FAU-CDI/wisski-distillery/internal/models"
_ "embed"
)
@ -22,7 +23,18 @@ var instanceProvisionTemplate = templating.Parse[instanceProvisionContext](
type instanceProvisionContext struct {
templating.RuntimeFlags
// nothing for the moment
systemParams
}
type systemParams struct {
PHPVersions []string
DefaultPHPVersion string
}
func newSystemParams() (sp systemParams) {
sp.PHPVersions = models.KnownPHPVersions()
sp.DefaultPHPVersion = models.DefaultPHPVersion
return sp
}
func (admin *Admin) instanceProvision(ctx context.Context) http.Handler {
@ -37,6 +49,7 @@ func (admin *Admin) instanceProvision(ctx context.Context) http.Handler {
)
return tpl.HTMLHandler(func(r *http.Request) (ipc instanceProvisionContext, err error) {
ipc.systemParams = newSystemParams()
return ipc, nil
})
}

View file

@ -0,0 +1,74 @@
package admin
import (
"context"
"html/template"
"net/http"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
"github.com/FAU-CDI/wisski-distillery/internal/models"
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
"github.com/julienschmidt/httprouter"
"github.com/tkw1536/pkglib/httpx"
_ "embed"
)
//go:embed "html/instance_rebuild.html"
var instanceRebuildHTML []byte
var instanceRebuildTemplate = templating.Parse[instanceRebuildContext](
"instance_rebuild.html", instanceRebuildHTML, nil,
templating.Title("Rebuild Instance"),
templating.Assets(assets.AssetsAdminRebuild),
)
type instanceRebuildContext struct {
templating.RuntimeFlags
Slug string
System models.System
systemParams
}
func (admin *Admin) instanceRebuild(ctx context.Context) http.Handler {
tpl := instanceRebuildTemplate.Prepare(
admin.Dependencies.Templating,
templating.Crumbs(
menuAdmin,
menuInstances,
menuInstance,
menuRebuild,
),
)
return tpl.HTMLHandlerWithFlags(func(r *http.Request) (ib instanceRebuildContext, funcs []templating.FlagFunc, err error) {
slug := httprouter.ParamsFromContext(r.Context()).ByName("slug")
var instance *wisski.WissKI
instance, err = admin.Dependencies.Instances.WissKI(r.Context(), slug)
if err == instances.ErrWissKINotFound {
return ib, nil, httpx.ErrNotFound
}
if err != nil {
return ib, nil, err
}
ib.Slug = instance.Slug
ib.System = instance.System
// replace the menu item
funcs = []templating.FlagFunc{
templating.ReplaceCrumb(menuInstance, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + instance.Slug)}),
templating.ReplaceCrumb(menuRebuild, component.MenuItem{Title: "Rebuild", Path: template.URL("/admin/rebuild/" + instance.Slug)}),
templating.Title(instance.Slug + " - Rebuild"),
}
ib.systemParams = newSystemParams()
return
})
}

View file

@ -8,6 +8,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/provision"
"github.com/FAU-CDI/wisski-distillery/internal/models"
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
)
@ -28,7 +29,7 @@ func (sockets *Sockets) Actions() ActionMap {
}),
"provision": sockets.Generic(1, func(ctx context.Context, sockets *Sockets, in io.Reader, out io.Writer, params ...string) error {
// read the flags of the instance to be provisioned
var flags provision.ProvisionFlags
var flags provision.Flags
if err := json.Unmarshal([]byte(params[0]), &flags); err != nil {
return err
}
@ -63,8 +64,13 @@ func (sockets *Sockets) Actions() ActionMap {
},
)
}),
"rebuild": sockets.Instance(0, func(ctx context.Context, _ *Sockets, instance *wisski.WissKI, in io.Reader, out io.Writer, params ...string) error {
return instance.Barrel().Build(ctx, out, true)
"rebuild": sockets.Instance(1, func(ctx context.Context, _ *Sockets, instance *wisski.WissKI, in io.Reader, out io.Writer, params ...string) error {
// read the flags of the instance to be provisioned
var system models.System
if err := json.Unmarshal([]byte(params[0]), &system); err != nil {
return err
}
return instance.SystemManager().Apply(ctx, out, system, true)
}),
"update": sockets.Instance(0, func(ctx context.Context, _ *Sockets, instance *wisski.WissKI, in io.Reader, out io.Writer, params ...string) error {
return instance.Drush().Update(ctx, out)