diff --git a/cmd/info.go b/cmd/info.go
index 35c779d..1494590 100644
--- a/cmd/info.go
+++ b/cmd/info.go
@@ -71,6 +71,7 @@ func (i info) Run(context wisski_distillery.Context) (err error) {
context.Printf("Last Update: %v\n", info.LastUpdate.String())
context.Printf("Last Cron: %v\n", info.LastCron.String())
+ context.Printf("Drupal Version: %v\n", info.DrupalVersion)
context.Printf("Theme: %v\n", info.Theme)
context.Printf("Bundles: (count %d)\n", info.Statistics.Bundles.TotalBundles)
diff --git a/cmd/provision.go b/cmd/provision.go
index 2744efa..3537d67 100644
--- a/cmd/provision.go
+++ b/cmd/provision.go
@@ -1,10 +1,13 @@
package cmd
import (
+ "encoding/json"
+
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
"github.com/FAU-CDI/wisski-distillery/internal/cli"
"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/ingredient/barrel/manager"
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
"github.com/tkw1536/goprogram/exit"
)
@@ -15,12 +18,26 @@ var Provision wisski_distillery.Command = pv{}
type pv struct {
PHPVersion string `short:"p" long:"php" description:"specific php version to use for instance. Should be one of '8.0', '8.1'."`
OPCacheDevelopment bool `short:"o" long:"opcache-devel" description:"Include opcache development configuration"`
+ Flavor string `short:"f" long:"flavor" description:"Use specific flavor. Use '--list-flavors' to list flavors. "`
+ ListFlavors bool `short:"l" long:"list-flavors" description:"List all known flavors"`
ContentSecurityPolicy string `short:"c" long:"content-security-policy" description:"Setup ContentSecurityPolicy"`
Positionals struct {
- Slug string `positional-arg-name:"slug" required:"1-1" description:"slug of instance to create"`
+ Slug string `positional-arg-name:"slug" description:"slug of instance to create"`
} `positional-args:"true"`
}
+var errMissingSlug = exit.Error{
+ ExitCode: exit.ExitCommandArguments,
+ Message: "must provide a slug",
+}
+
+func (pv pv) AfterParse() error {
+ if !pv.ListFlavors && pv.Positionals.Slug == "" {
+ return errMissingSlug
+ }
+ return nil
+}
+
func (pv) Description() wisski_distillery.Description {
return wisski_distillery.Description{
Requirements: cli.Requirements{
@@ -39,8 +56,13 @@ var errProvisionGeneric = exit.Error{
// TODO: AfterParse to check instance!
func (p pv) Run(context wisski_distillery.Context) error {
+ if p.ListFlavors {
+ return p.listFlavors(context)
+ }
+
instance, err := context.Environment.Provision().Provision(context.Stderr, context.Context, provision.Flags{
- Slug: p.Positionals.Slug,
+ Slug: p.Positionals.Slug,
+ Flavor: p.Flavor,
System: models.System{
PHP: p.PHPVersion,
OpCacheDevelopment: p.OPCacheDevelopment,
@@ -48,7 +70,7 @@ func (p pv) Run(context wisski_distillery.Context) error {
},
})
if err != nil {
- return errProvisionGeneric.WithMessageF(p.Positionals.Slug).Wrap(err)
+ return errProvisionGeneric.WithMessageF(p.Positionals.Slug).WrapError(err)
}
// and we're done!
@@ -59,3 +81,10 @@ func (p pv) Run(context wisski_distillery.Context) error {
return nil
}
+
+func (pv) listFlavors(context wisski_distillery.Context) error {
+ encoder := json.NewEncoder(context.Stdout)
+ encoder.SetIndent("", " ")
+ encoder.Encode(manager.Profiles())
+ return nil
+}
diff --git a/internal/dis/component/provision/provision.go b/internal/dis/component/provision/provision.go
index e186730..6ec008c 100644
--- a/internal/dis/component/provision/provision.go
+++ b/internal/dis/component/provision/provision.go
@@ -30,28 +30,47 @@ type Flags struct {
// Slug is the slug of the wisski instance
Slug string
+ // Flavor is the name of the profile to use
+ Flavor string `json:",omitempty"`
+
// System is information about the system
System models.System
}
// Profile returns the profile belonging to this provision flags.
-func (flags Flags) Profile() manager.Profile {
- // TODO: Actually do something here
- return manager.Profile{}
+func (flags Flags) Profile() (profile manager.Profile) {
+ // if no flavor was given, apply the default profile
+ if flags.Flavor == "" {
+ profile.Apply(manager.LoadDefaultProfile())
+ return
+ }
+
+ // load the selector profile!
+ profile.Apply(manager.LoadProfile(flags.Flavor))
+ return
}
var ErrInstanceAlreadyExists = errors.New("instance with provided slug already exists")
-func (pv *Provision) Validate(flags Flags) error {
+func (pv *Provision) validate(flags Flags) error {
// check the slug
if _, err := pv.dependencies.Instances.IsValidSlug(flags.Slug); err != nil {
return err
}
+ // check that we know the flavor
+ if flags.Flavor != "" && !manager.HasProfile(flags.Flavor) {
+ return fmt.Errorf("unknown flavor %q", flags.Flavor)
+ }
return nil
}
// Provision provisions a new docker compose instance.
func (pv *Provision) Provision(progress io.Writer, ctx context.Context, flags Flags) (*wisski.WissKI, error) {
+ // validate that everything is correct
+ if err := pv.validate(flags); err != nil {
+ return nil, err
+ }
+
// check that it doesn't already exist
logging.LogMessage(progress, "Provisioning new WissKI instance %s", flags.Slug)
if exists, err := pv.dependencies.Instances.Has(ctx, flags.Slug); err != nil || exists {
diff --git a/internal/dis/component/server/admin/admin.go b/internal/dis/component/server/admin/admin.go
index 079e582..bd56c73 100644
--- a/internal/dis/component/server/admin/admin.go
+++ b/internal/dis/component/server/admin/admin.go
@@ -69,11 +69,10 @@ var (
menuProvision = component.MenuItem{Title: "Provision", Path: "/admin/instances/provision/"}
- menuInstances = component.MenuItem{Title: "Instances", Path: "/admin/instances/"}
- menuInstance = component.DummyMenuItem()
- menuRebuild = component.DummyMenuItem()
- menuGrants = component.DummyMenuItem()
- menuIngredients = component.DummyMenuItem()
+ menuInstances = component.MenuItem{Title: "Instances", Path: "/admin/instances/"}
+ menuInstance = component.DummyMenuItem()
+ menuRebuild = component.DummyMenuItem()
+ menuGrants = component.DummyMenuItem()
)
func (admin *Admin) HandleRoute(ctx context.Context, route string) (handler http.Handler, err error) {
diff --git a/internal/dis/component/server/admin/html/instance.html b/internal/dis/component/server/admin/html/instance.html
index 3c7d61c..4e47d68 100644
--- a/internal/dis/component/server/admin/html/instance.html
+++ b/internal/dis/component/server/admin/html/instance.html
@@ -91,14 +91,6 @@
-
-
- PHP Version
-
-
- {{ .Instance.System.PHP }}
-
-
Docker Base Image
@@ -107,6 +99,14 @@
{{ .Instance.System.GetDockerBaseImage }}
+
+
+ PHP Version
+
+
+ {{ .Instance.System.PHP }}
+
+
OPCache Development Config
@@ -143,36 +143,20 @@
- Theme
+ Drupal Version
+
+
+ {{ .Info.DrupalVersion }}
+
+
+
+
+ Default Theme
{{ .Info.Theme }}
-
-
- Docker Base Image
-
-
- {{ .Instance.System.GetDockerBaseImage }}
-
-
-
-
- OPCache Development Config
-
-
- {{ .Instance.System.OpCacheDevelopment }}
-
-
-
-
- Content Security Policy
-
-
- {{ .Instance.System.ContentSecurityPolicy }}
-
-
diff --git a/internal/dis/component/server/admin/html/instance_system.html b/internal/dis/component/server/admin/html/instance_system.html
index e88d0ae..6b72e61 100644
--- a/internal/dis/component/server/admin/html/instance_system.html
+++ b/internal/dis/component/server/admin/html/instance_system.html
@@ -67,12 +67,23 @@
{{ if not $rebuild }}
-
Profile
+
Flavor
-
- In the future, it will be possible to configure the Drupal, WissKI and Module versions here.
- But this is not yet implemented.
+
+
+ Determine the set of module(s) to install for this WissKI.
+ Changing this after installation may not be possible and in any case requires manual intervention.
+
+
+ {{ $defaultProfile := .DefaultProfile }}
+ {{ range $name, $description := .Profiles }}
+
+ {{ end }}
{{ end }}
diff --git a/internal/dis/component/server/admin/instance.go b/internal/dis/component/server/admin/instance.go
index 9968d86..961a622 100644
--- a/internal/dis/component/server/admin/instance.go
+++ b/internal/dis/component/server/admin/instance.go
@@ -43,7 +43,6 @@ func (admin *Admin) instance(ctx context.Context) http.Handler {
templating.Actions(
menuRebuild,
menuGrants,
- menuIngredients,
),
)
diff --git a/internal/dis/component/server/admin/instance_provision.go b/internal/dis/component/server/admin/instance_provision.go
index 551f7fd..2f33d05 100644
--- a/internal/dis/component/server/admin/instance_provision.go
+++ b/internal/dis/component/server/admin/instance_provision.go
@@ -6,6 +6,8 @@ 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/wisski/ingredient/barrel/manager"
+ "github.com/tkw1536/pkglib/collection"
_ "embed"
)
@@ -26,6 +28,8 @@ func (admin *Admin) instanceProvision(ctx context.Context) http.Handler {
return tpl.HTMLHandler(func(r *http.Request) (ipc instanceSystemContext, err error) {
ipc.prepare(false)
+ ipc.DefaultProfile = manager.DefaultProfile()
+ ipc.Profiles = collection.MapValues(manager.Profiles(), func(_ string, profile manager.Profile) string { return profile.Description })
return ipc, nil
})
}
diff --git a/internal/dis/component/server/admin/instance_rebuild.go b/internal/dis/component/server/admin/instance_rebuild.go
index 3b586d0..75ec07c 100644
--- a/internal/dis/component/server/admin/instance_rebuild.go
+++ b/internal/dis/component/server/admin/instance_rebuild.go
@@ -36,6 +36,10 @@ type instanceSystemContext struct {
Rebuild bool
Slug string
System models.System
+
+ // list of known profiles and their descriptions
+ DefaultProfile string
+ Profiles map[string]string
}
// prepare prares the given instanceSystemContent
diff --git a/internal/dis/component/server/assets/assets_disclaimer.txt b/internal/dis/component/server/assets/assets_disclaimer.txt
index 6449aee..38d5be0 100644
--- a/internal/dis/component/server/assets/assets_disclaimer.txt
+++ b/internal/dis/component/server/assets/assets_disclaimer.txt
@@ -423,7 +423,7 @@ SOFTWARE.
-----
-The following software may be included in this product: @parcel/bundler-default, @parcel/cache, @parcel/codeframe, @parcel/compressor-raw, @parcel/config-default, @parcel/core, @parcel/diagnostic, @parcel/events, @parcel/fs, @parcel/fs-search, @parcel/graph, @parcel/hash, @parcel/logger, @parcel/markdown-ansi, @parcel/namer-default, @parcel/node-resolver-core, @parcel/optimizer-css, @parcel/optimizer-htmlnano, @parcel/optimizer-image, @parcel/optimizer-svgo, @parcel/optimizer-swc, @parcel/package-manager, @parcel/packager-css, @parcel/packager-html, @parcel/packager-js, @parcel/packager-raw, @parcel/packager-svg, @parcel/plugin, @parcel/profiler, @parcel/reporter-cli, @parcel/reporter-dev-server, @parcel/reporter-tracer, @parcel/resolver-default, @parcel/runtime-browser-hmr, @parcel/runtime-js, @parcel/runtime-react-refresh, @parcel/runtime-service-worker, @parcel/transformer-babel, @parcel/transformer-css, @parcel/transformer-html, @parcel/transformer-image, @parcel/transformer-js, @parcel/transformer-json, @parcel/transformer-postcss, @parcel/transformer-posthtml, @parcel/transformer-raw, @parcel/transformer-react-refresh-wrap, @parcel/transformer-svg, @parcel/types, @parcel/utils, @parcel/watcher, @parcel/watcher-darwin-arm64, @parcel/workers, parcel. A copy of the source code may be downloaded from https://github.com/parcel-bundler/parcel.git (@parcel/bundler-default), https://github.com/parcel-bundler/parcel.git (@parcel/cache), https://github.com/parcel-bundler/parcel.git (@parcel/codeframe), https://github.com/parcel-bundler/parcel.git (@parcel/compressor-raw), https://github.com/parcel-bundler/parcel.git (@parcel/config-default), https://github.com/parcel-bundler/parcel.git (@parcel/core), https://github.com/parcel-bundler/parcel.git (@parcel/diagnostic), https://github.com/parcel-bundler/parcel.git (@parcel/events), https://github.com/parcel-bundler/parcel.git (@parcel/fs), https://github.com/parcel-bundler/parcel.git (@parcel/fs-search), https://github.com/parcel-bundler/parcel.git (@parcel/graph), https://github.com/parcel-bundler/parcel.git (@parcel/hash), https://github.com/parcel-bundler/parcel.git (@parcel/logger), https://github.com/parcel-bundler/parcel.git (@parcel/markdown-ansi), https://github.com/parcel-bundler/parcel.git (@parcel/namer-default), https://github.com/parcel-bundler/parcel.git (@parcel/node-resolver-core), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-css), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-htmlnano), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-image), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-svgo), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-swc), https://github.com/parcel-bundler/parcel.git (@parcel/package-manager), https://github.com/parcel-bundler/parcel.git (@parcel/packager-css), https://github.com/parcel-bundler/parcel.git (@parcel/packager-html), https://github.com/parcel-bundler/parcel.git (@parcel/packager-js), https://github.com/parcel-bundler/parcel.git (@parcel/packager-raw), https://github.com/parcel-bundler/parcel.git (@parcel/packager-svg), https://github.com/parcel-bundler/parcel.git (@parcel/plugin), https://github.com/parcel-bundler/parcel.git (@parcel/profiler), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-cli), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-dev-server), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-tracer), https://github.com/parcel-bundler/parcel.git (@parcel/resolver-default), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-browser-hmr), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-js), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-react-refresh), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-service-worker), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-babel), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-css), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-html), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-image), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-js), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-json), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-postcss), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-posthtml), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-raw), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-react-refresh-wrap), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-svg), https://github.com/parcel-bundler/parcel.git (@parcel/types), https://github.com/parcel-bundler/parcel.git (@parcel/utils), https://github.com/parcel-bundler/watcher.git (@parcel/watcher), https://github.com/parcel-bundler/watcher.git (@parcel/watcher-darwin-arm64), https://github.com/parcel-bundler/parcel.git (@parcel/workers), https://github.com/parcel-bundler/parcel.git (parcel). This software contains the following license and notice below:
+The following software may be included in this product: @parcel/bundler-default, @parcel/cache, @parcel/codeframe, @parcel/compressor-raw, @parcel/config-default, @parcel/core, @parcel/diagnostic, @parcel/events, @parcel/fs, @parcel/fs-search, @parcel/graph, @parcel/hash, @parcel/logger, @parcel/markdown-ansi, @parcel/namer-default, @parcel/node-resolver-core, @parcel/optimizer-css, @parcel/optimizer-htmlnano, @parcel/optimizer-image, @parcel/optimizer-svgo, @parcel/optimizer-swc, @parcel/package-manager, @parcel/packager-css, @parcel/packager-html, @parcel/packager-js, @parcel/packager-raw, @parcel/packager-svg, @parcel/plugin, @parcel/profiler, @parcel/reporter-cli, @parcel/reporter-dev-server, @parcel/reporter-tracer, @parcel/resolver-default, @parcel/runtime-browser-hmr, @parcel/runtime-js, @parcel/runtime-react-refresh, @parcel/runtime-service-worker, @parcel/transformer-babel, @parcel/transformer-css, @parcel/transformer-html, @parcel/transformer-image, @parcel/transformer-js, @parcel/transformer-json, @parcel/transformer-postcss, @parcel/transformer-posthtml, @parcel/transformer-raw, @parcel/transformer-react-refresh-wrap, @parcel/transformer-svg, @parcel/types, @parcel/utils, @parcel/watcher, @parcel/watcher-linux-x64-glibc, @parcel/watcher-linux-x64-musl, @parcel/workers, parcel. A copy of the source code may be downloaded from https://github.com/parcel-bundler/parcel.git (@parcel/bundler-default), https://github.com/parcel-bundler/parcel.git (@parcel/cache), https://github.com/parcel-bundler/parcel.git (@parcel/codeframe), https://github.com/parcel-bundler/parcel.git (@parcel/compressor-raw), https://github.com/parcel-bundler/parcel.git (@parcel/config-default), https://github.com/parcel-bundler/parcel.git (@parcel/core), https://github.com/parcel-bundler/parcel.git (@parcel/diagnostic), https://github.com/parcel-bundler/parcel.git (@parcel/events), https://github.com/parcel-bundler/parcel.git (@parcel/fs), https://github.com/parcel-bundler/parcel.git (@parcel/fs-search), https://github.com/parcel-bundler/parcel.git (@parcel/graph), https://github.com/parcel-bundler/parcel.git (@parcel/hash), https://github.com/parcel-bundler/parcel.git (@parcel/logger), https://github.com/parcel-bundler/parcel.git (@parcel/markdown-ansi), https://github.com/parcel-bundler/parcel.git (@parcel/namer-default), https://github.com/parcel-bundler/parcel.git (@parcel/node-resolver-core), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-css), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-htmlnano), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-image), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-svgo), https://github.com/parcel-bundler/parcel.git (@parcel/optimizer-swc), https://github.com/parcel-bundler/parcel.git (@parcel/package-manager), https://github.com/parcel-bundler/parcel.git (@parcel/packager-css), https://github.com/parcel-bundler/parcel.git (@parcel/packager-html), https://github.com/parcel-bundler/parcel.git (@parcel/packager-js), https://github.com/parcel-bundler/parcel.git (@parcel/packager-raw), https://github.com/parcel-bundler/parcel.git (@parcel/packager-svg), https://github.com/parcel-bundler/parcel.git (@parcel/plugin), https://github.com/parcel-bundler/parcel.git (@parcel/profiler), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-cli), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-dev-server), https://github.com/parcel-bundler/parcel.git (@parcel/reporter-tracer), https://github.com/parcel-bundler/parcel.git (@parcel/resolver-default), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-browser-hmr), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-js), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-react-refresh), https://github.com/parcel-bundler/parcel.git (@parcel/runtime-service-worker), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-babel), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-css), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-html), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-image), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-js), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-json), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-postcss), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-posthtml), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-raw), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-react-refresh-wrap), https://github.com/parcel-bundler/parcel.git (@parcel/transformer-svg), https://github.com/parcel-bundler/parcel.git (@parcel/types), https://github.com/parcel-bundler/parcel.git (@parcel/utils), https://github.com/parcel-bundler/watcher.git (@parcel/watcher), https://github.com/parcel-bundler/watcher.git (@parcel/watcher-linux-x64-glibc), https://github.com/parcel-bundler/watcher.git (@parcel/watcher-linux-x64-musl), https://github.com/parcel-bundler/parcel.git (@parcel/workers), https://github.com/parcel-bundler/parcel.git (parcel). This software contains the following license and notice below:
MIT License
@@ -4426,7 +4426,7 @@ OTHER DEALINGS IN THE SOFTWARE.
-----
-The following software may be included in this product: lightningcss, lightningcss-darwin-arm64. A copy of the source code may be downloaded from https://github.com/parcel-bundler/lightningcss.git (lightningcss), https://github.com/parcel-bundler/lightningcss.git (lightningcss-darwin-arm64). This software contains the following license and notice below:
+The following software may be included in this product: lightningcss, lightningcss-linux-x64-gnu, lightningcss-linux-x64-musl. A copy of the source code may be downloaded from https://github.com/parcel-bundler/lightningcss.git (lightningcss), https://github.com/parcel-bundler/lightningcss.git (lightningcss-linux-x64-gnu), https://github.com/parcel-bundler/lightningcss.git (lightningcss-linux-x64-musl). This software contains the following license and notice below:
Mozilla Public License Version 2.0
==================================
diff --git a/internal/dis/component/server/assets/assets_dist.go b/internal/dis/component/server/assets/assets_dist.go
index e739aa3..582015b 100644
--- a/internal/dis/component/server/assets/assets_dist.go
+++ b/internal/dis/component/server/assets/assets_dist.go
@@ -30,7 +30,7 @@ var AssetsAdmin = Assets{
// AssetsAdminProvision contains assets for the 'AdminProvision' entrypoint.
var AssetsAdminProvision = Assets{
- Scripts: ``,
+ Scripts: ``,
Styles: ``,
}
diff --git a/internal/dis/component/server/assets/dist/AdminProvision.3981a5f2.js b/internal/dis/component/server/assets/dist/AdminProvision.3981a5f2.js
deleted file mode 100644
index 200261c..0000000
--- a/internal/dis/component/server/assets/dist/AdminProvision.3981a5f2.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(){var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},t={},n={},o=e.parcelRequireafa4;null==o&&((o=function(e){if(e in t)return t[e].exports;if(e in n){var o=n[e];delete n[e];var r={id:e,exports:{}};return t[e]=r,o.call(r.exports,r,r.exports),r.exports}var i=Error("Cannot find module '"+e+"'");throw i.code="MODULE_NOT_FOUND",i}).register=function(e,t){n[e]=t},e.parcelRequireafa4=o),o("dK5Bi");var r=o("8vh0V");async function i(e){return await new Promise((t,n)=>{(0,r.createModal)("provision",[JSON.stringify(e)],{bufferSize:0,onClose:(o,r)=>{if(!o){n(Error(r??"unspecified error"));return}t(e.Slug)}})})}let l=document.getElementById("system"),a=document.getElementById("slug"),d=document.getElementById("php"),u=document.getElementById("opcacheDevelopment"),c=document.getElementById("contentsecuritypolicy");l.addEventListener("submit",e=>{e.preventDefault(),i({Slug:a.value,System:{PHP:d.value,OpCacheDevelopment:u.checked,ContentSecurityPolicy:c.value}}).then(e=>{location.href="/admin/instance/"+e}).catch(e=>{console.error(e),location.reload()})}),l.querySelector("fieldset")?.removeAttribute("disabled")}();
\ No newline at end of file
diff --git a/internal/dis/component/server/assets/dist/AdminProvision.53660f24.js b/internal/dis/component/server/assets/dist/AdminProvision.53660f24.js
new file mode 100644
index 0000000..d5d40dd
--- /dev/null
+++ b/internal/dis/component/server/assets/dist/AdminProvision.53660f24.js
@@ -0,0 +1 @@
+!function(){var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},t={},n={},o=e.parcelRequireafa4;null==o&&((o=function(e){if(e in t)return t[e].exports;if(e in n){var o=n[e];delete n[e];var r={id:e,exports:{}};return t[e]=r,o.call(r.exports,r,r.exports),r.exports}var l=Error("Cannot find module '"+e+"'");throw l.code="MODULE_NOT_FOUND",l}).register=function(e,t){n[e]=t},e.parcelRequireafa4=o),o("dK5Bi");var r=o("8vh0V");async function l(e){return await new Promise((t,n)=>{(0,r.createModal)("provision",[JSON.stringify(e)],{bufferSize:0,onClose:(o,r)=>{if(!o){n(Error(r??"unspecified error"));return}t(e.Slug)}})})}let i=document.getElementById("system"),a=document.getElementById("slug"),u=document.getElementById("php"),c=document.getElementById("opcacheDevelopment"),d=document.getElementById("contentsecuritypolicy");i.addEventListener("submit",e=>{e.preventDefault();let t=document.querySelector('input[name="flavor"]:checked'),n=t instanceof HTMLInputElement?t.value:"";l({Slug:a.value,Flavor:n,System:{PHP:u.value,OpCacheDevelopment:c.checked,ContentSecurityPolicy:d.value}}).then(e=>{location.href="/admin/instance/"+e}).catch(e=>{console.error(e),location.reload()})}),i.querySelector("fieldset")?.removeAttribute("disabled")}();
\ No newline at end of file
diff --git a/internal/dis/component/server/assets/dist/AdminProvision.5bc6b324.js b/internal/dis/component/server/assets/dist/AdminProvision.5bc6b324.js
new file mode 100644
index 0000000..8542508
--- /dev/null
+++ b/internal/dis/component/server/assets/dist/AdminProvision.5bc6b324.js
@@ -0,0 +1 @@
+var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},t={},n={},o=e.parcelRequireafa4;null==o&&((o=function(e){if(e in t)return t[e].exports;if(e in n){var o=n[e];delete n[e];var r={id:e,exports:{}};return t[e]=r,o.call(r.exports,r,r.exports),r.exports}var l=Error("Cannot find module '"+e+"'");throw l.code="MODULE_NOT_FOUND",l}).register=function(e,t){n[e]=t},e.parcelRequireafa4=o),o("8xGhL");var r=o("12vpF");async function l(e){return await new Promise((t,n)=>{(0,r.createModal)("provision",[JSON.stringify(e)],{bufferSize:0,onClose:(o,r)=>{if(!o){n(Error(r??"unspecified error"));return}t(e.Slug)}})})}const i=document.getElementById("system"),a=document.getElementById("slug"),u=document.getElementById("php"),c=document.getElementById("opcacheDevelopment"),d=document.getElementById("contentsecuritypolicy");i.addEventListener("submit",e=>{e.preventDefault();let t=document.querySelector('input[name="flavor"]:checked'),n=t instanceof HTMLInputElement?t.value:"";l({Slug:a.value,Flavor:n,System:{PHP:u.value,OpCacheDevelopment:c.checked,ContentSecurityPolicy:d.value}}).then(e=>{location.href="/admin/instance/"+e}).catch(e=>{console.error(e),location.reload()})}),i.querySelector("fieldset")?.removeAttribute("disabled");
\ No newline at end of file
diff --git a/internal/dis/component/server/assets/dist/AdminProvision.7dff6f1a.js b/internal/dis/component/server/assets/dist/AdminProvision.7dff6f1a.js
deleted file mode 100644
index 5a727a4..0000000
--- a/internal/dis/component/server/assets/dist/AdminProvision.7dff6f1a.js
+++ /dev/null
@@ -1 +0,0 @@
-var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},t={},n={},o=e.parcelRequireafa4;null==o&&((o=function(e){if(e in t)return t[e].exports;if(e in n){var o=n[e];delete n[e];var r={id:e,exports:{}};return t[e]=r,o.call(r.exports,r,r.exports),r.exports}var i=Error("Cannot find module '"+e+"'");throw i.code="MODULE_NOT_FOUND",i}).register=function(e,t){n[e]=t},e.parcelRequireafa4=o),o("8xGhL");var r=o("12vpF");async function i(e){return await new Promise((t,n)=>{(0,r.createModal)("provision",[JSON.stringify(e)],{bufferSize:0,onClose:(o,r)=>{if(!o){n(Error(r??"unspecified error"));return}t(e.Slug)}})})}const l=document.getElementById("system"),a=document.getElementById("slug"),d=document.getElementById("php"),u=document.getElementById("opcacheDevelopment"),c=document.getElementById("contentsecuritypolicy");l.addEventListener("submit",e=>{e.preventDefault(),i({Slug:a.value,System:{PHP:d.value,OpCacheDevelopment:u.checked,ContentSecurityPolicy:c.value}}).then(e=>{location.href="/admin/instance/"+e}).catch(e=>{console.error(e),location.reload()})}),l.querySelector("fieldset")?.removeAttribute("disabled");
\ No newline at end of file
diff --git a/internal/dis/component/server/assets/src/entry/AdminProvision/index.ts b/internal/dis/component/server/assets/src/entry/AdminProvision/index.ts
index b9114ee..0088ee5 100644
--- a/internal/dis/component/server/assets/src/entry/AdminProvision/index.ts
+++ b/internal/dis/component/server/assets/src/entry/AdminProvision/index.ts
@@ -13,7 +13,14 @@ const contentSecurityPolicy = document.getElementById('contentsecuritypolicy') a
system.addEventListener('submit', (evt) => {
evt.preventDefault()
- Provision({ Slug: slug.value, System: { PHP: php.value, OpCacheDevelopment: opcacheDevelopment.checked, ContentSecurityPolicy: contentSecurityPolicy.value } })
+ const flavorElement = document.querySelector('input[name="flavor"]:checked');
+ const flavor = (flavorElement instanceof HTMLInputElement) ? flavorElement.value : "";
+
+ Provision({
+ Slug: slug.value,
+ Flavor: flavor,
+ System: { PHP: php.value, OpCacheDevelopment: opcacheDevelopment.checked, ContentSecurityPolicy: contentSecurityPolicy.value }
+ })
.then(slug => {
location.href = '/admin/instance/' + slug
})
diff --git a/internal/dis/component/server/assets/src/lib/remote/api.ts b/internal/dis/component/server/assets/src/lib/remote/api.ts
index 2beba1e..ceddf9b 100644
--- a/internal/dis/component/server/assets/src/lib/remote/api.ts
+++ b/internal/dis/component/server/assets/src/lib/remote/api.ts
@@ -6,6 +6,7 @@ import { createModal } from '~/src/lib/remote'
*/
interface ProvisionFlags {
Slug: string
+ Flavor?: string
System: System
}
diff --git a/internal/status/wisski.go b/internal/status/wisski.go
index 1b3e41f..6c7cf54 100644
--- a/internal/status/wisski.go
+++ b/internal/status/wisski.go
@@ -29,8 +29,8 @@ type WissKI struct {
LastUpdate time.Time
LastCron time.Time
- // current theme
- Theme string
+ DrupalVersion string // current drupal version
+ Theme string // current default theme
// Statistics of the WissKI
Statistics Statistics
diff --git a/internal/wisski/ingredient/barrel/manager/manager.go b/internal/wisski/ingredient/barrel/manager/manager.go
index 5e6eba6..eb8f993 100644
--- a/internal/wisski/ingredient/barrel/manager/manager.go
+++ b/internal/wisski/ingredient/barrel/manager/manager.go
@@ -1,6 +1,9 @@
package manager
import (
+ "maps"
+ "slices"
+
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient"
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/barrel"
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/barrel/composer"
@@ -27,8 +30,81 @@ type Manager struct {
}
}
+// profiles contains the list of default profiles
+var (
+ defaultProfile = "Drupal 10"
+ profiles = map[string]Profile{
+ "Drupal 9": {
+ Description: "Legacy Version of Drupal with default packages",
+
+ Drupal: "^9",
+ WissKI: "",
+ InstallModules: []string{
+ "drupal/inline_entity_form:^1.0@RC",
+ "drupal/imagemagick",
+ "drupal/image_effects",
+ "drupal/colorbox",
+ },
+ EnableModules: []string{
+ "drupal/devel:^4.1",
+ "drupal/geofield:^1.40",
+ "drupal/geofield_map:^2.85",
+ "drupal/imce:^2.4",
+ "drupal/remove_generator:^2.0",
+ },
+ },
+ "Drupal 10": {
+ Description: "Current Version of Drupal with default packages",
+
+ Drupal: "^10",
+ WissKI: "",
+ InstallModules: []string{
+
+ "drupal/inline_entity_form:^1.0@RC",
+ "drupal/imagemagick",
+ "drupal/image_effects",
+ "drupal/colorbox",
+ },
+ EnableModules: []string{
+ "drupal/devel:^5.0",
+ "drupal/geofield:^1.56",
+ "drupal/geofield_map:^3.0",
+ "drupal/imce:^3.0",
+ "drupal/remove_generator:^2.0",
+ },
+ },
+ }
+)
+
+// TODO: All of these should move to the config
+
+func LoadDefaultProfile() Profile {
+ return LoadProfile(DefaultProfile())
+}
+
+func Profiles() map[string]Profile {
+ return maps.Clone(profiles)
+}
+
+func LoadProfile(name string) Profile {
+ return profiles[name]
+}
+
+func HasProfile(name string) bool {
+ _, ok := profiles[name]
+ return ok
+}
+
+func DefaultProfile() string {
+ return defaultProfile
+}
+
// Profile represents a profile applied to a WissKI instance of the Distillery.
type Profile struct {
+ // Description is a human-readable description for this profile.
+ // It is only used by the frontend.
+ Description string
+
Drupal string // Version of Drupal to use
WissKI string // Version of WissKI to use
@@ -36,29 +112,25 @@ type Profile struct {
EnableModules []string // Modules to be installed and enabled
}
-// DefaultDrupalVersion is the default drupal version
-const DefaultDrupalVersion = "^9.0.0"
-
-// ApplyDefaults applies the default settings to missing profile settings.
-func (profile *Profile) ApplyDefaults() {
+// Apply copies over defaults from the other profile to this one.
+// If a field is already set, no defaults are copied.
+func (profile *Profile) Apply(other Profile) {
if profile.Drupal == "" {
- profile.Drupal = DefaultDrupalVersion
+ profile.Drupal = other.Drupal
+ }
+ if profile.WissKI == "" {
+ profile.WissKI = other.WissKI
}
if profile.InstallModules == nil {
- profile.InstallModules = []string{
- "drupal/inline_entity_form:^1.0@RC",
- "drupal/imagemagick",
- "drupal/image_effects",
- "drupal/colorbox",
- }
+ profile.InstallModules = slices.Clone(other.InstallModules)
}
if profile.EnableModules == nil {
- profile.EnableModules = []string{
- "drupal/devel:^4.1",
- "drupal/geofield:^1.40",
- "drupal/geofield_map:^2.85",
- "drupal/imce:^2.4",
- "drupal/remove_generator:^2.0",
- }
+ profile.EnableModules = slices.Clone(profile.EnableModules)
}
}
+
+// ApplyDefaults loads some set of defaults.
+// If all fields are set, no defaults are applied.
+func (profile *Profile) ApplyDefaults() {
+ profile.Apply(profiles[defaultProfile])
+}
diff --git a/internal/wisski/ingredient/barrel/manager/provision.go b/internal/wisski/ingredient/barrel/manager/provision.go
index 912027f..3acf4ac 100644
--- a/internal/wisski/ingredient/barrel/manager/provision.go
+++ b/internal/wisski/ingredient/barrel/manager/provision.go
@@ -57,8 +57,6 @@ func (manager *Manager) Provision(ctx context.Context, progress io.Writer, syste
manager.dependencies.Barrel.Stack().DownAll(anyways, progress)
}()
- // Apply the defaults to the flags
- flags.ApplyDefaults()
return manager.bootstrap(ctx, progress, flags)
}
@@ -71,7 +69,6 @@ var drushVariants = []string{
// Applies defaults to the flags.
func (provision *Manager) bootstrap(ctx context.Context, progress io.Writer, flags Profile) error {
// TODO: Check if we can remove the easyrdf patch!
-
flags.ApplyDefaults()
logging.LogMessage(progress, "Creating Composer Project")
diff --git a/internal/wisski/ingredient/php/extras/settings.php b/internal/wisski/ingredient/php/extras/settings.php
index 504cb3f..1dafaee 100644
--- a/internal/wisski/ingredient/php/extras/settings.php
+++ b/internal/wisski/ingredient/php/extras/settings.php
@@ -10,7 +10,7 @@ function get_setting($name) {
/** sets a setting in 'settings.php' */
function set_setting(string $name, mixed $value): bool {
// find settings.php
- $filename = DRUPAL_ROOT . "/" . \Drupal::service("site.path") . "/settings.php";
+ $filename = DRUPAL_ROOT . "/" . \Drupal::getContainer()->getParameter("site.path") . "/settings.php";
// setup user write permissions for the file
$old = fileperms($filename);
diff --git a/internal/wisski/ingredient/php/extras/version.go b/internal/wisski/ingredient/php/extras/version.go
new file mode 100644
index 0000000..7fb8744
--- /dev/null
+++ b/internal/wisski/ingredient/php/extras/version.go
@@ -0,0 +1,37 @@
+package extras
+
+import (
+ "context"
+
+ "github.com/FAU-CDI/wisski-distillery/internal/phpx"
+ "github.com/FAU-CDI/wisski-distillery/internal/status"
+ "github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient"
+ "github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/php"
+
+ _ "embed"
+)
+
+// Version implements reading the current drupal version
+type Version struct {
+ ingredient.Base
+ dependencies struct {
+ PHP *php.PHP
+ }
+}
+
+// Get returns the currently active theme
+func (v *Version) Get(ctx context.Context, server *phpx.Server) (version string, err error) {
+ err = v.dependencies.PHP.EvalCode(
+ ctx, server, &version, "return Drupal::VERSION; ",
+ )
+ return
+}
+
+func (v *Version) Fetch(flags ingredient.FetcherFlags, info *status.WissKI) (err error) {
+ if flags.Quick {
+ return
+ }
+
+ info.DrupalVersion, _ = v.Get(flags.Context, flags.Server)
+ return
+}
diff --git a/internal/wisski/ingredients.go b/internal/wisski/ingredients.go
deleted file mode 100644
index 9a3ff40..0000000
--- a/internal/wisski/ingredients.go
+++ /dev/null
@@ -1 +0,0 @@
-package wisski
diff --git a/internal/wisski/wisski.go b/internal/wisski/wisski.go
index b2e2164..c40d77a 100644
--- a/internal/wisski/wisski.go
+++ b/internal/wisski/wisski.go
@@ -144,6 +144,7 @@ func (wisski *WissKI) allIngredients(context *lifetime.RegisterContext[ingredien
lifetime.Place[*extras.Requirements](context)
lifetime.Place[*extras.Adapters](context)
lifetime.Place[*extras.Theme](context)
+ lifetime.Place[*extras.Version](context)
lifetime.Place[*users.Users](context)
lifetime.Place[*users.UserPolicy](context)