Implement basic flavor support
This commit is contained in:
parent
9a3e508ce8
commit
d6c0c465e4
24 changed files with 246 additions and 82 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -91,14 +91,6 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
PHP Version
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ .Instance.System.PHP }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Docker Base Image
|
||||
|
|
@ -107,6 +99,14 @@
|
|||
<code>{{ .Instance.System.GetDockerBaseImage }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
PHP Version
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ .Instance.System.PHP }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
OPCache Development Config
|
||||
|
|
@ -143,36 +143,20 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Theme
|
||||
Drupal Version
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ .Info.DrupalVersion }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Default Theme
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ .Info.Theme }}</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>
|
||||
<tr>
|
||||
<td>
|
||||
Content Security Policy
|
||||
</td>
|
||||
<td>
|
||||
<code>{{ .Instance.System.ContentSecurityPolicy }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -67,12 +67,23 @@
|
|||
|
||||
{{ if not $rebuild }}
|
||||
<div class="pure-controls">
|
||||
<h5>Profile</h5>
|
||||
<h5>Flavor</h5>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
In the future, it will be possible to configure the Drupal, WissKI and Module versions here.
|
||||
But this is not yet implemented.
|
||||
<div class="pure-controls">
|
||||
<span class="pure-form-message-inline">
|
||||
Determine the set of module(s) to install for this WissKI. <br />
|
||||
Changing this after installation may not be possible and in any case requires manual intervention.
|
||||
</span>
|
||||
|
||||
{{ $defaultProfile := .DefaultProfile }}
|
||||
{{ range $name, $description := .Profiles }}
|
||||
<label for="flavor-{{ $name }}" class="pure-radio">
|
||||
<input type="radio" id="flavor-{{ $name }}" name="flavor" value="{{ $name }}" {{ if eq $name $defaultProfile }}checked{{ end }} />
|
||||
<b>{{ $name }}</b>
|
||||
{{ $description }}
|
||||
</label>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ func (admin *Admin) instance(ctx context.Context) http.Handler {
|
|||
templating.Actions(
|
||||
menuRebuild,
|
||||
menuGrants,
|
||||
menuIngredients,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -30,7 +30,7 @@ var AssetsAdmin = Assets{
|
|||
|
||||
// AssetsAdminProvision contains assets for the 'AdminProvision' entrypoint.
|
||||
var AssetsAdminProvision = Assets{
|
||||
Scripts: `<script nomodule defer src="/⛰/User.869c9a74.js"></script><script nomodule defer src="/⛰/Admin.b992cf94.js"></script><script type="module" src="/⛰/User.23a71b44.js"></script><script type="module" src="/⛰/Admin.c0a122d2.js"></script><script type="module" src="/⛰/Default.38d394c2.js"></script><script src="/⛰/Default.38d394c2.js" nomodule defer></script><script type="module" src="/⛰/AdminProvision.7dff6f1a.js"></script><script src="/⛰/AdminProvision.3981a5f2.js" nomodule defer></script>`,
|
||||
Scripts: `<script nomodule defer src="/⛰/User.869c9a74.js"></script><script nomodule defer src="/⛰/Admin.b992cf94.js"></script><script type="module" src="/⛰/User.23a71b44.js"></script><script type="module" src="/⛰/Admin.c0a122d2.js"></script><script type="module" src="/⛰/Default.38d394c2.js"></script><script src="/⛰/Default.38d394c2.js" nomodule defer></script><script type="module" src="/⛰/AdminProvision.5bc6b324.js"></script><script src="/⛰/AdminProvision.53660f24.js" nomodule defer></script>`,
|
||||
Styles: `<link rel="stylesheet" href="/⛰/Default.a1620182.css"><link rel="stylesheet" href="/⛰/Admin.db3e959a.css"><link rel="stylesheet" href="/⛰/User.68febbf8.css"><link rel="stylesheet" href="/⛰/User.09b09c46.css"><link rel="stylesheet" href="/⛰/Admin.9d294a13.css"><link rel="stylesheet" href="/⛰/AdminProvision.38d394c2.css">`,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")}();
|
||||
1
internal/dis/component/server/assets/dist/AdminProvision.53660f24.js
vendored
Normal file
1
internal/dis/component/server/assets/dist/AdminProvision.53660f24.js
vendored
Normal file
|
|
@ -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")}();
|
||||
1
internal/dis/component/server/assets/dist/AdminProvision.5bc6b324.js
vendored
Normal file
1
internal/dis/component/server/assets/dist/AdminProvision.5bc6b324.js
vendored
Normal file
|
|
@ -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");
|
||||
|
|
@ -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");
|
||||
|
|
@ -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
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { createModal } from '~/src/lib/remote'
|
|||
*/
|
||||
interface ProvisionFlags {
|
||||
Slug: string
|
||||
Flavor?: string
|
||||
System: System
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
37
internal/wisski/ingredient/php/extras/version.go
Normal file
37
internal/wisski/ingredient/php/extras/version.go
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
package wisski
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue