From d114c8fafe8ab184e894d56f98b09caf23b3bf01 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Thu, 29 Jun 2023 11:05:40 +0200 Subject: [PATCH] Add support for php 8.1 This commit adds optional support for basing images on php 8.1 as opposed to php 8.0. --- cmd/provision.go | 4 ++- cmd/reserve.go | 2 +- internal/dis/component/instances/create.go | 31 ++++++++++++++++++- .../dis/component/instances/purger/purger.go | 2 +- internal/dis/component/provision/provision.go | 18 ++++++++++- .../component/server/admin/html/instance.html | 12 +++++++ internal/models/instances.go | 3 ++ internal/wisski/ingredient/barrel/barrel.env | 3 +- .../ingredient/barrel/barrel/Dockerfile | 3 +- .../barrel/barrel/docker-compose.yml | 6 +++- .../barrel/scripts/provision_container.sh | 14 ++++++++- internal/wisski/ingredient/barrel/stack.go | 2 ++ 12 files changed, 91 insertions(+), 9 deletions(-) diff --git a/cmd/provision.go b/cmd/provision.go index 7e15e7f..4684e35 100644 --- a/cmd/provision.go +++ b/cmd/provision.go @@ -12,6 +12,7 @@ import ( 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'."` Positionals struct { Slug string `positional-arg-name:"slug" required:"1-1" description:"slug of instance to create"` } `positional-args:"true"` @@ -36,7 +37,8 @@ var errProvisionGeneric = exit.Error{ func (p pv) Run(context wisski_distillery.Context) error { instance, err := context.Environment.Provision().Provision(context.Stderr, context.Context, provision.ProvisionFlags{ - Slug: p.Positionals.Slug, + Slug: p.Positionals.Slug, + PHPVersion: p.PHPVersion, }) if err != nil { return errProvisionGeneric.WithMessageF(p.Positionals.Slug).Wrap(err) diff --git a/cmd/reserve.go b/cmd/reserve.go index b82198a..08cd30c 100644 --- a/cmd/reserve.go +++ b/cmd/reserve.go @@ -53,7 +53,7 @@ func (r reserve) Run(context wisski_distillery.Context) (err error) { } // make it in-memory - instance, err := dis.Instances().Create(slug) + instance, err := dis.Instances().Create(slug, "") if err != nil { return errProvisionGeneric.WithMessageF(slug, err) } diff --git a/internal/dis/component/instances/create.go b/internal/dis/component/instances/create.go index b1bfab6..9e18848 100644 --- a/internal/dis/component/instances/create.go +++ b/internal/dis/component/instances/create.go @@ -14,11 +14,34 @@ var ( errRestrictedSlug = errors.New("restricted slug") ) +const ( + PHP8 = "8.0" + PHP8_IMAGE = "docker.io/library/php:8.0-apache-bullseye" + PHP8_1 = "8.1" + PHP8_1_IMAGE = "docker.io/library/php:8.1-apache-bullseye" +) + +var errUnknownPHPVersion = errors.New("unknown php version") + +// GetBaseImage returns the php base image to use +func GetBaseImage(php string) (string, error) { + switch php { + case "": + return PHP8_IMAGE, nil + case PHP8: + return PHP8_IMAGE, nil + case PHP8_1: + return PHP8_1_IMAGE, nil + default: + return "", errUnknownPHPVersion + } +} + // Create fills the struct for a new WissKI instance. // It validates that slug is a valid name for an instance. // // It does not perform any checks if the instance already exists, or does the creation in the database. -func (instances *Instances) Create(slug string) (wissKI *wisski.WissKI, err error) { +func (instances *Instances) Create(slug string, phpversion string) (wissKI *wisski.WissKI, err error) { // make sure that the slug is valid! slug, err = instances.IsValidSlug(slug) @@ -64,6 +87,12 @@ func (instances *Instances) Create(slug string) (wissKI *wisski.WissKI, err erro return nil, err } + // docker image + wissKI.Liquid.Instance.DockerBaseImage, err = GetBaseImage(phpversion) + if err != nil { + return nil, err + } + // store the instance in the object and return it! return wissKI, nil } diff --git a/internal/dis/component/instances/purger/purger.go b/internal/dis/component/instances/purger/purger.go index 8755f0c..c61e179 100644 --- a/internal/dis/component/instances/purger/purger.go +++ b/internal/dis/component/instances/purger/purger.go @@ -37,7 +37,7 @@ func (purger *Purger) Purge(ctx context.Context, out io.Writer, slug string) err instance, err := purger.Dependencies.Instances.WissKI(ctx, slug) if err == instances.ErrWissKINotFound { fmt.Fprintln(out, "Not found in bookkeeping table, assuming defaults") - instance, err = purger.Dependencies.Instances.Create(slug) + instance, err = purger.Dependencies.Instances.Create(slug, "") } if err != nil { return errPurgeNoDetails.WithMessageF(err) diff --git a/internal/dis/component/provision/provision.go b/internal/dis/component/provision/provision.go index 4786715..c664e85 100644 --- a/internal/dis/component/provision/provision.go +++ b/internal/dis/component/provision/provision.go @@ -22,11 +22,27 @@ type Provision struct { // ProvisionFlags are flags for a new instance type ProvisionFlags struct { + // Slug is the slug of the wisski instance Slug string + + // PHP Version to use + PHPVersion string } var ErrInstanceAlreadyExists = errors.New("instance with provided slug already exists") +func (pv *Provision) ValidateFlags(flags ProvisionFlags) error { + // check the slug + if _, err := pv.Dependencies.Instances.IsValidSlug(flags.Slug); err != nil { + return err + } + // check for known php versions + if _, err := instances.GetBaseImage(flags.PHPVersion); err != nil { + return err + } + return nil +} + // Provision provisions a new docker compose instance. func (pv *Provision) Provision(progress io.Writer, ctx context.Context, flags ProvisionFlags) (*wisski.WissKI, error) { // check that it doesn't already exist @@ -36,7 +52,7 @@ func (pv *Provision) Provision(progress io.Writer, ctx context.Context, flags Pr } // make it in-memory - instance, err := pv.Dependencies.Instances.Create(flags.Slug) + instance, err := pv.Dependencies.Instances.Create(flags.Slug, flags.PHPVersion) if err != nil { return nil, err } diff --git a/internal/dis/component/server/admin/html/instance.html b/internal/dis/component/server/admin/html/instance.html index 5d83a5c..d707792 100644 --- a/internal/dis/component/server/admin/html/instance.html +++ b/internal/dis/component/server/admin/html/instance.html @@ -29,6 +29,18 @@ {{ .Info.URL }} + + + Docker Base Image + + + {{ if .Instance.DockerBaseImage }} + {{ .Instance.DockerBaseImage }} + {{ else }} + (none) + {{ end }} + + Running diff --git a/internal/models/instances.go b/internal/models/instances.go index fd0ce34..d601121 100644 --- a/internal/models/instances.go +++ b/internal/models/instances.go @@ -34,6 +34,9 @@ type Instance struct { // The filesystem path the system can be found under FilesystemBase string `gorm:"column:filesystem_base;not null"` + // DockerBaseImage is the php base image to use + DockerBaseImage string `gorm:"column:docker_base;not_null` + // SQL Database credentials for the system SqlDatabase string `gorm:"column:sql_database;not null"` SqlUsername string `gorm:"column:sql_user;not null"` diff --git a/internal/wisski/ingredient/barrel/barrel.env b/internal/wisski/ingredient/barrel/barrel.env index 557330b..23006c4 100644 --- a/internal/wisski/ingredient/barrel/barrel.env +++ b/internal/wisski/ingredient/barrel/barrel.env @@ -6,4 +6,5 @@ WISSKI_HOSTNAME=${HOSTNAME} HOST_RULE=${HOST_RULE} DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME} -HTTPS_ENABLED=${HTTPS_ENABLED} \ No newline at end of file +HTTPS_ENABLED=${HTTPS_ENABLED} +BARREL_BASE_IMAGE=${BARREL_BASE_IMAGE} diff --git a/internal/wisski/ingredient/barrel/barrel/Dockerfile b/internal/wisski/ingredient/barrel/barrel/Dockerfile index ffedbcb..15f12e4 100644 --- a/internal/wisski/ingredient/barrel/barrel/Dockerfile +++ b/internal/wisski/ingredient/barrel/barrel/Dockerfile @@ -1,4 +1,5 @@ -FROM docker.io/library/php:8.0-apache-bullseye +ARG BARREL_BASE_IMAGE +FROM $BARREL_BASE_IMAGE ARG COMPOSER_VERSION=2.3.8 WORKDIR /var/www diff --git a/internal/wisski/ingredient/barrel/barrel/docker-compose.yml b/internal/wisski/ingredient/barrel/barrel/docker-compose.yml index 9afb9e8..8af42e4 100644 --- a/internal/wisski/ingredient/barrel/barrel/docker-compose.yml +++ b/internal/wisski/ingredient/barrel/barrel/docker-compose.yml @@ -2,7 +2,11 @@ version: "3.7" services: barrel: - build: . + build: + context: . + args: + BARREL_BASE_IMAGE: ${BARREL_BASE_IMAGE} + restart: always hostname: ${WISSKI_HOSTNAME} diff --git a/internal/wisski/ingredient/barrel/barrel/scripts/provision_container.sh b/internal/wisski/ingredient/barrel/barrel/scripts/provision_container.sh index 88d7fef..d8d806f 100644 --- a/internal/wisski/ingredient/barrel/barrel/scripts/provision_container.sh +++ b/internal/wisski/ingredient/barrel/barrel/scripts/provision_container.sh @@ -85,6 +85,18 @@ function composer_install_and_enable() { done } +function try_variants() { + for var in "$@" + do + if composer require --dry-run "$var" > /dev/null 2>&1; then + composer require "$var" + return 0; + fi + done + + return 1; +} + # Create a new composer project. log_info " => Creating composer project" @@ -99,7 +111,7 @@ composer --no-interaction config allow-plugins true # Install drush so that we can automate a lot of things log_info " => Installing 'drush'" -composer require drush/drush +try_variants 'drush/drush' 'drush/drush:^12' 'drush/drush:^11' || (echo "No version of Drush is installable" && false) # Use 'drush' to run the site-installation. # Here we need to use the username, password and database creds we made above. diff --git a/internal/wisski/ingredient/barrel/stack.go b/internal/wisski/ingredient/barrel/stack.go index 01c1999..860b677 100644 --- a/internal/wisski/ingredient/barrel/stack.go +++ b/internal/wisski/ingredient/barrel/stack.go @@ -31,6 +31,8 @@ func (barrel *Barrel) Stack() component.StackWithResources { "DATA_PATH": filepath.Join(barrel.FilesystemBase, "data"), "RUNTIME_DIR": barrel.Malt.Config.Paths.RuntimeDir(), + + "BARREL_BASE_IMAGE": barrel.DockerBaseImage, }, MakeDirs: []string{"data", ".composer"},