Initial __nextcloud type

This type should work, but there are still many things to do here to
work nice and well.

Things that currently not work (well):
  - not all parameters work for now
  - nextcloud installations in subfolders (e.g. slashes in the object id)
This commit is contained in:
matze 2020-10-24 09:05:22 +02:00
parent ce20c67602
commit 979398e398
15 changed files with 655 additions and 0 deletions

View file

@ -0,0 +1,28 @@
#!/bin/sh -e
# __nextcloud/explorer/config
# Checks the nextcloud configuration
# Get the installdir
user="$( cat "$__object/parameter/user" )"
installdir="$( "$__type_explorer/installdir" )"
# Check if the tools are available
if [ -d "$installdir" ]; then
cd "$installdir"
# if those files exist, everything should be good
if [ -f "occ" ] && [ -f "config/config.php" ]; then
# dump out config instead of fuzz every possible option through
# `occ config:system:get`. Or parse through the whole json or
# yaml-like output of `occ config:list system --private`.
php -r 'require("lib/private/Config.php"); $config = new OC\Config("config/");
function printv($key, $value) {printf("%s = %s\n", $key, $value);}
foreach($config->getKeys() as $key){
$value = $config->getValue($key);
if(is_array($value)) foreach($value as $n => $in) printv($n."|".$key, $in);
else printv($key, $value);
};'
fi
fi

View file

@ -0,0 +1,16 @@
#!/bin/sh -e
# __nextcloud/explorer/installdir
# Detects the directory nextcloud should be installed to.
# by parameter or auto-detection
webroot="$( "$__type_explorer/webroot" )"
if [ -z "$webroot" ]; then
echo "no installdir given and no webroot directory found" >&2
echo "no place to install found; set it via --webroot" >&2
exit 1
fi
# assemble directory with the object id
printf "%s/%s\n" "$webroot" "$__object_id"

View file

@ -0,0 +1,19 @@
#!/bin/sh -e
# __nextcloud/explorer/version
# Check the currently installed version. Outputs nothing if nothing found.
# Get the install directory
installdir="$( "$__type_explorer/installdir" )"
# Check if the installation directory exists
if [ -d "$installdir" ]; then
cd "$installdir"
# if those files exist, everything should be good
if [ -f "occ" ] && [ -f "version.php" ]; then
# detect php version with the version file
php -r 'require("version.php"); print($OC_VersionString);'
fi
fi

View file

@ -0,0 +1,34 @@
#!/bin/sh -e
# __nextcloud/explorer/webroot
# Detects the webroot if any
# Just check if there is some directory and echo + exit on success
#
# Arguments:
# 1: the directory to check
check_dir() {
if [ -d "$1" ]; then
echo "$1"
exit
fi
}
# Check the user choice
parameter="$__object/parameter/webroot"
if [ -f "$parameter" ]; then
cat "$parameter"
exit
fi
# Maybe checking standard webserver configs ..
# Check if there are default directories
check_dir "/srv/www"
check_dir "/var/www/html"
check_dir "/var/www"
# do nothing if no webroot found

209
type/__nextcloud/gencode-remote Executable file
View file

@ -0,0 +1,209 @@
#!/bin/sh -e
# __nextcloud/gencode-remote
# Install if not installed
# Legacy:
# curl -sS -L '$nextcloud_uri' | tar xj --strip-components=1 nextcloud/
# Call the nextcloud occ script as the designed user. Maybe this can be a bit
# more effictive with user switching, but currently the easiest way of doing
# it.
#
# All arguments are directly passed to occ (injection alarm ;-) )
occ() {
# su creates a new shell, so it does not affect the current session
# will not use -q as it supresses errors, too
cat << SHELL
su -s /bin/sh -l "$user" -- -e <<SU
cd '$installdir' && php occ --no-interaction $@
SU
SHELL
}
# Get existing versions
version_is="$( cat "$__object/explorer/version" )"
version_should="$( cat "$__object/parameter/version" )"
# the install directory
installdir="$( cat "$__object/explorer/installdir" )"
updatedir="$( dirname "$installdir" )"
tarballdir="$updatedir/.$__object_id"
# get used user and group
user="$( cat "$__object/parameter/user" )"
group="$( cat "$__object/parameter/group" )"
# Detect if we can install or upgrade.
# Check if this will be a new installation.
if [ -z "$version_is" ]; then
install="yes"
# Check if upgrades are available. Not do this if it's not wanted by the user.
elif ! [ -f "$__object/parameter/install-only" ]; then
# installation upgrade
if [ "$version_is" != "$version_should" ]; then
upgrade="yes"
fi
fi
# Check if the installation will be upgraded.
# Remove the old folder and replace it with the new one.
if [ "$upgrade" ]; then
cat << REMOTE
cd '$updatedir'
chown '$user':'$group' -R '$tarballdir'
REMOTE
occ maintenance:mode --on
cat << REMOTE
cp -pf '$installdir/config/config.php' '$tarballdir/config/config.php'
mv '$installdir/data' '$tarballdir'
rm -rf '$installdir'
mv '$tarballdir' '$installdir'
cd '$installdir'
REMOTE
# do some maintainer stuff
occ upgrade
occ db:add-missing-columns
occ db:add-missing-indices
# send upgrade message
printf "upgraded %s to %s\n" "$version_is" "$version_should" >> "$__messages_out"
# Apply some misc to the installation folder.
elif [ "$install" ]; then
cat << REMOTE
chown '$user':'$group' -R '$installdir'
REMOTE
fi
# Check if the nextcloud application needs to be installed.
# This checks the state of the configuration, not of the directory.
if ! grep -q -F "installed = 1" "$__object/explorer/config"; then
# argument construction
occ_install_args=""
# Database
db_setup() {
if ! [ -f "$__object/parameter/db-host" ]; then
echo "no hostname given! can't proceed." >&2
exit 3
fi
occ_install_args="$occ_install_args --database '$1'"
occ_install_args="$occ_install_args --database-host '$(cat "$__object/parameter/db-host")'"
db_name="$__object/parameter/database-name"
if [ -f "$db_name" ]; then
occ_install_args="$occ_install_args --database-name '$(cat "$db_name")'"
fi
db_user="$__object/parameter/database-user"
if [ -f "$db_user" ]; then
occ_install_args="$occ_install_args --database-user '$(cat "$db_user")'"
fi
db_pass="$__object/parameter/database-password"
if [ -f "$db_pass" ]; then
occ_install_args="$occ_install_args --database-pass '$(cat "$db_pass")'"
fi
db_prefix="$__object/parameter/database-prefix"
if [ -f "$db_prefix" ]; then
occ_install_args="$occ_install_args --database-table-prefix '$(cat "$db_prefix")'"
fi
}
database_type="$(cat "$__object/parameter/database-type")"
case "$database_type" in
sqlite|sqlite3)
occ_install_args="$occ_install_args --database sqlite"
;;
mysql|mariadb)
db_setup mysql
;;
pgsql|postgres|postgresql)
db_setup pgsql
;;
*)
printf "Database type '%s' is unkown!\n" "" >&2
exit 3
;;
esac
# Admin stuff
occ_install_args="$occ_install_args --admin-pass '$(cat "$__object/parameter/admin-password")'"
admin_user="$__object/parameter/admin-user"
if [ -f "$admin_user" ]; then
occ_install_args="$occ_install_args --admin-user '$(cat "$admin_user")'"
fi
admin_email="$__object/parameter/admin-email"
if [ -f "$admin_email" ]; then
occ_install_args="$occ_install_args --admin-email '$(cat "$admin_email")'"
fi
# Data directory
datadir="$__object/parameter/datadir"
if [ -f "$datadir" ]; then
occ_install_args="$occ_install_args --data-dir '$(cat "$datadir")'"
fi
# Execute the install command
occ maintenance:install $occ_install_args
# send install message
echo installed >> "$__messages_out"
fi
# Handle the config
mkdir "$__object/files"
"$__type/map-conf-changes.sh" > "$__object/files/conf-cmds"
# only print if there are changes listed
if [ -s "$__object/files/conf-cmds" ]; then
# save that we did changes
changes="yes"
# print change commands incl. the switch of user context
# using -e to abort if the commands failed
printf "su -s /bin/sh -l '%s' -- -e << 'SU'\n" "$user"
printf "cd '%s'\n" "$installdir"
cat "$__object/files/conf-cmds"
printf "SU\n"
# print a message
echo config >> "$__messages_out"
fi
# Check if this is the fist install
if [ "$install" ]; then
# do some convert stuff etc.
# variable accessible from the last $install if-clause
case "$database_type" in
mysql|mariadb)
# only available for mysql
occ db:convert-mysql-charset
;;
esac
occ db:convert-filecache-bigint
fi
# Disable maintainer mode
if [ "$install" ] || [ "$upgrade" ] || [ "$changes" ]; then
occ maintenance:mode --off
fi

132
type/__nextcloud/manifest Executable file
View file

@ -0,0 +1,132 @@
#!/bin/sh -e
# __nextcloud/manifest
# Version compare function original from __sensible_editor
#
# Arguments:
# 1: version of which $2 should be checked against
# 2: version which should be bigger than or equal with $1
#
# Return code:
# 0: $1 is bigger than $2
# 1-n: $1 is smaller than or equal $2
version_ge() {
printf "%s" "$1" | awk -F '[^0-9.]' -v target="$2" '
function max(x, y) { return x > y ? x : y }
BEGIN {
getline
nx = split($1, x, ".")
ny = split(target, y, ".")
for (i = 1; i <= max(nx, ny); ++i) {
diff = int(x[i]) - int(y[i])
if (diff == 0) continue
exit (diff < 0)
}
exit 1
}'; return $?
}
# Check support status
os="$(cat "$__global/explorer/os")"
case "$os" in
debian|ubuntu)
# PHP main
__package php-cli
# to unpack the package
__package bzip2
# install misc packages for nextcloud
__package ffmpeg
# PHP modules
for package in php-gd php-json php-mysql php-curl php-mbstring php-intl \
php-imagick php-xml php-zip php-bz2 php-bcmath php-gmp
do
require="__package/php-cli" __package $package
done
# check support database additions (but don't remove junk of old ones)
case "$(cat "$__object/parameter/database-type")" in
sqlite|sqlite3)
__package php-sqlite3
;;
mysql|mariadb)
__package php-mysql
;;
pgsql|postgres|postgresql)
__package php-pgsql
;;
esac
;;
# unkown distro - what to install?
*)
printf "unkown %s, don't know what to install ..\n" "$os" >&2
echo "checkout the __nextcloud/manifest to contribute a working package list" >&2
exit 1
;;
esac
# Get the user and group
mode="$(cat "$__object/parameter/mode")"
user="$(cat "$__object/parameter/user")"
group="$(cat "$__object/parameter/group")"
# Get the installation directory
webroot="$(cat "$__object/explorer/webroot")"
installdir="$(cat "$__object/explorer/installdir")"
# Set permissions after the nextcloud installation/upgrade is done
# FIXME maybe less strict if some parameter is not given by the user?
# permissions also partily set via the gencode-remote
require="__nextcloud/$__object_id" __directory "$installdir" \
--mode "$mode" --owner "$user" --group "$group"
# Get version information
version_is="$( cat "$__object/explorer/version" )"
version_should="$( cat "$__object/parameter/version" )"
# The version URI
nextcloud_uri="https://download.nextcloud.com/server/releases/nextcloud-${version_should}.tar.bz2"
nextcloud_sum="${nextcloud_uri}.sha256"
# Only check if there is a current installation
if [ "$version_is" ]; then
# Block downgrades as there are may caused from the automatic upgrader
# if the current version is higher than the version that should be installed
if version_ge "$version_is" "$version_should"; then
# it's an error if the current version is higher than the one that should be installed
printf "The current nextcloud version '%s' is higher than the version that should be installed (%s)\n" \
"$version_is" "$version_should" >&2
printf "Please bump the nextcloud version to '%s' or higher!\n" "$version_is" >&2
exit 2
fi
# Set destination to a temporary directory
destination="$webroot/.$__object_id"
else
# Set destination to the real destination
destination="$webroot/$__object_id"
fi
# Upgrade the nextcloud version
if [ "$version_is" != "$version_should" ]; then
updatedir="$( dirname "$installdir" )"
# Be sure the parent directory exists for installation
__directory "$updatedir" --parents
require="__directory$updatedir" \
__download "$updatedir/nextcloud.tar.bz2" \
--url "$nextcloud_uri" \
--sum "sha256:$(curl -sS -L "$nextcloud_sum" | awk '{print $1}')" # must be a required parameter??
require="__download$updatedir/nextcloud.tar.bz2" \
__unpack "$updatedir/nextcloud.tar.bz2" \
--tar-strip 1 \
--destination "$destination"
fi

View file

@ -0,0 +1,196 @@
#!/bin/sh -e
# __nextcloud/map-conf-changes.sh
# The environment variable "$install" should be set if nextcloud was installed
# now. This changes the behaviour to not trust gathered values from the
# explorer.
# Test if the value exists as given.
#
# Arguments:
# 1: The nextcloud config name
# 2: The value that should be set
#
# Return code:
# 0: value exactly matched
# 1: value not matched or do not exist
testparam() {
# short-circuit after installation; the explorer may not be valid
if [ "$install" ]; then return 1; fi
if grep -q -F "$1 = $2" "$__object/explorer/config"; then
return 0
else
return 1
fi
}
# Test if the parameter is somehow set.
#
# Arguments:
# 1: The nextcloud config name
#
# Return code:
# 0: param exists
# 1: param not found
paramexist() {
# short-circuit after installation; the explorer may not be valid
if [ "$install" ]; then return 0; fi
if grep -q "^$1 = " "$__object/explorer/config"; then
return 0
else
return 1
fi
}
# Base for the basic function types.
#
# Arguments:
# 1: cdist type parameter name
# 2: nextcloud config name
# 3: occ printf pattern to set the value
conf_base() {
if [ -f "$__object/parameter/$1" ]; then
value="$(cat "$__object/parameter/$1")"
if ! testparam "$2" "$value"; then
# set it because it does not exist
printf "php occ config:system:$3\n" "$2" "$value"
fi
else
if paramexist "$2"; then
# remove it because it exists
printf "php occ config:system:delete '%s'\n" "$2"
fi
fi
}
# Set's the cdist parameter value to nextcloud as specific value.
#
# Arguments:
# 1: cdist type parameter name
# 2: nextcloud config name
conf_string() {
conf_base "$1" "$2" "set '%s' --type=string --value='%s'"
}
conf_number() {
conf_base "$1" "$2" "set '%s' --type=integer --value='%s'"
}
conf_decimal() {
conf_base "$1" "$2" "set '%s' --type=double --value='%s'"
}
# Sets the nextcloud configuration option after a boolean cdist parameter.
#
# Arguments:
# 1: cdist type parameter name
# 2: nextcloud config name
conf_boolean() {
# map parameter to a php boolean (are outputted as 0 or 1)
if [ -f "$__object/parameter/$1" ]; then
testval="1"
value="true"
else
testval="0"
value="false"
fi
if ! testparam "$2" "$testval"; then
# set it if does not already exist
printf "php occ config:system:set '%s' --type=boolean --value=%s\n" "$2" "$value"
fi
}
# Corrects the array after all values given by the parameter. Values not given
# to this type will be removed.
#
# Arguments:
# 1: cdist type parameter name
# 2: nextcloud config name
conf_array() {
if [ -f "$__object/parameter/$1" ]; then
# reset array if installation is fresh
if [ "$install" ]; then
# just remove everything, because we don't know it
printf "php occ config:system:delete '%s' || true\n" "$2"
# counter is zero for sure
counter=0
# else, default behaviour of the array
else
# save counter of the next free index
counter=$( awk -v FS=" = " -v name="$2" '
BEGIN { counter = 0 }
split($1, header, "|") == 2 && header[1] ~ /^[[:digit:]]+$/ && header[2] == name \
{ if(counter < header[1]) counter = header[1] }
END { print counter + 1 }
' "$__object/explorer/config"
)
# create a file which contains all lines not already resolved by this function
_dir="$__object/files/conf-arrays"
mkdir -p "$_dir"
grep "^[[:digit:]]*|$2 = " "$__object/explorer/config" > "$_dir/$2" || true # ignore not found
fi
# iterate through every value
while read -r value; do
# check every value if he exists
if ! grep -q "^[[:digit:]]*|$2 = $value$" "$__object/explorer/config"; then
# add this value
printf "php occ config:system:set '%s' '%s' --type=string --value='%s'\n" \
"$2" "$(( counter ))" "$value"
counter=$(( counter + 1 ))
fi
if [ -z "$install" ]; then
# removes it from the list of unhandled values
grep -v "^[[:digit:]]*|$2 = $value$" "$_dir/$2" > "$_dir/$2_tmp" || true # ignore not found
mv "$_dir/$2_tmp" "$_dir/$2" # because we can't do `cat foo > foo`
fi
done < "$__object/parameter/$1"
if [ -z "$install" ]; then
# interate through the leftover values
# remove them, as they should not exist (at least can be)
while read -r start equal value; do
# remove those specific elements from the array
printf "php occ config:system:delete '%s' '%s' --error-if-not-exists\n" \
"$2" "$( printf "%s" "$start" | awk -F'|' '{print $1}' )"
done < "$_dir/$2"
fi
else
# remove everything because we don't know which was set by the user
if paramexist "$2"; then
# remove the whole array
printf "php occ config:system:delete '%s'\n" "$2"
fi
fi
}
# Set the install variable if nextcloud was not installed before this type.
if ! testparam installed 1; then
install="yes"
fi
# Map all parameters
# Generate the config changes
# misc
conf_array host trusted_domains
# Already set via the installer
if [ -z "$install" ]; then
# db
conf_string database-type dbtype
conf_string database-host dbhost # FIXME host included here (takes port also)
conf_string database-name dbname
conf_string database-user dbuser
conf_string database-password dbpassword
conf_string database-prefix dbtableprefix
fi

View file

@ -0,0 +1 @@
install-only

View file

@ -0,0 +1 @@
sqlite3

View file

@ -0,0 +1 @@
www-data

View file

@ -0,0 +1 @@
755

View file

@ -0,0 +1 @@
www-data

View file

@ -0,0 +1,13 @@
mode
user
group
webroot
database-type
database-host
database-name
database-user
database-password
database-prefix
admin-user
admin-email
data-directory

View file

@ -0,0 +1 @@
host

View file

@ -0,0 +1,2 @@
version
admin-password