forked from 0k/0k-charms
Compare commits
merge into: bgallet:master
bgallet:0k/dev/master
bgallet:backup
bgallet:boris/docuseal
bgallet:boris/matomo
bgallet:boris/rallly
bgallet:boris/smtp-extern
bgallet:charm-codimd-new
bgallet:cups_service_alpha
bgallet:dev
bgallet:dev1
bgallet:dhcp
bgallet:discourse
bgallet:element
bgallet:etherpad-upd
bgallet:framadate
bgallet:hedgedoc
bgallet:lokavaluto/dev/master
bgallet:master
bgallet:matomo
bgallet:nanoyaml
bgallet:netdata
bgallet:new-mailhog-charms
bgallet:new-monujo-options
bgallet:nextcloud
bgallet:nj-collabra-office
bgallet:nj-keycloak-17.0
bgallet:nj-organice-charm
bgallet:nj-vaulwarden-migrate
bgallet:odoo_fix_webhook_url
bgallet:postgres
bgallet:rallly
bgallet:test
bgallet:upd-docker
bgallet:update-latest-synapse
bgallet:wip
0k:0k/dev/master
0k:backup
0k:boris/smtp-extern
0k:charm-codimd-new
0k:cups_service_alpha
0k:dev
0k:dev1
0k:dhcp
0k:element
0k:etherpad-upd
0k:framadate
0k:lokavaluto/dev/master
0k:master
0k:matomo
0k:new-mailhog-charms
0k:new-monujo-options
0k:nj-collabra-office
0k:nj-keycloak-17.0
0k:nj-organice-charm
0k:nj-vaulwarden-migrate
0k:ntfy-install
0k:odoo_fix_webhook_url
0k:postgres
0k:test
0k:upd-docker
0k:update-latest-synapse
0k:wip
pull from: bgallet:matomo
bgallet:0k/dev/master
bgallet:backup
bgallet:boris/docuseal
bgallet:boris/matomo
bgallet:boris/rallly
bgallet:boris/smtp-extern
bgallet:charm-codimd-new
bgallet:cups_service_alpha
bgallet:dev
bgallet:dev1
bgallet:dhcp
bgallet:discourse
bgallet:element
bgallet:etherpad-upd
bgallet:framadate
bgallet:hedgedoc
bgallet:lokavaluto/dev/master
bgallet:master
bgallet:matomo
bgallet:nanoyaml
bgallet:netdata
bgallet:new-mailhog-charms
bgallet:new-monujo-options
bgallet:nextcloud
bgallet:nj-collabra-office
bgallet:nj-keycloak-17.0
bgallet:nj-organice-charm
bgallet:nj-vaulwarden-migrate
bgallet:odoo_fix_webhook_url
bgallet:postgres
bgallet:rallly
bgallet:test
bgallet:upd-docker
bgallet:update-latest-synapse
bgallet:wip
0k:0k/dev/master
0k:backup
0k:boris/smtp-extern
0k:charm-codimd-new
0k:cups_service_alpha
0k:dev
0k:dev1
0k:dhcp
0k:element
0k:etherpad-upd
0k:framadate
0k:lokavaluto/dev/master
0k:master
0k:matomo
0k:new-mailhog-charms
0k:new-monujo-options
0k:nj-collabra-office
0k:nj-keycloak-17.0
0k:nj-organice-charm
0k:nj-vaulwarden-migrate
0k:ntfy-install
0k:odoo_fix_webhook_url
0k:postgres
0k:test
0k:upd-docker
0k:update-latest-synapse
0k:wip
4 Commits
Author | SHA1 | Message | Date |
---|---|---|---|
Valentin Lab | 3cb15b9350 |
new: [matomo] add charm
|
6 months ago |
Valentin Lab | b8bf3ed2f5 |
fix: [rsync-backup-target] make target accept ``rsync`` client ``3.2.0``
Starting from ``3.2.0`` introduced ``Ivu`` server commands, these are now accepted. |
6 months ago |
Boris Gallet | 09fa2678a4 |
new: [smtp-stub] new charm
|
7 months ago |
Valentin Lab | 74c434c64f |
new: [postgres] add ``upgrade`` action
|
7 months ago |
10 changed files with 955 additions and 2 deletions
-
24matomo/hooks/init
-
26matomo/hooks/mysql_database-relation-joined
-
117matomo/hooks/post_deploy
-
77matomo/hooks/publish_dir-relation-joined
-
95matomo/lib/common
-
45matomo/metadata.yml
-
540postgres/actions/upgrade
-
4rsync-backup-target/build/src/usr/local/sbin/ssh-cmd-validate
-
18smtp-stub/hooks/smtp_server-relation-joined
-
11smtp-stub/metadata.yml
@ -0,0 +1,24 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
## Init is run on host |
||||
|
## For now it is run every time the script is launched, but |
||||
|
## it should be launched only once after build. |
||||
|
|
||||
|
## Accessible variables are: |
||||
|
## - SERVICE_NAME Name of current service |
||||
|
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any |
||||
|
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service |
||||
|
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service |
||||
|
|
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
## If no admin-password set, fail |
||||
|
options-get admin-password |
||||
|
|
||||
|
|
||||
|
matomo:init |
||||
|
|
||||
|
matomo:config |
@ -0,0 +1,26 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
|
||||
|
## XXXvlab: should get location of code |
||||
|
#CONFIG=$(echo $COMPOSE_CONFIG | shyaml get-value $SERVICE_NAME.relations.publish-dir...) |
||||
|
# CONFIG="$SERVICE_DATASTORE/opt/apps/piwigo/local/config/database.inc.php" |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
PASSWORD="$(relation-get password)" |
||||
|
USER="$(relation-get user)" |
||||
|
DBNAME="$(relation-get dbname)" |
||||
|
|
||||
|
|
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database host "\"$TARGET_SERVICE_NAME\"" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database username "\"$USER\"" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database password "\"$PASSWORD\"" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database dbname "\"$DBNAME\"" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database tables_prefix "\"\"" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" database charset "\"utf8mb4\"" |
||||
|
|
||||
|
info "Configured $SERVICE_NAME code for $TARGET_SERVICE_NAME access." |
||||
|
|
@ -0,0 +1,117 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
## If no admin-password set, then don't try to pre-initialize database |
||||
|
admin_password=$(options-get admin-password 2>/dev/null) || exit 0 |
||||
|
admin_email=$(options-get admin-email 2>/dev/null ) || true |
||||
|
|
||||
|
CONTROL="$SERVICE_DATASTORE/.control" |
||||
|
## Was it already properly propagated to database ? |
||||
|
control=$(H "${admin_password}" "${admin_email}") |
||||
|
if [ -e "$CONTROL" ]; then |
||||
|
if [ "$control" == "$(cat "$CONTROL")" ]; then |
||||
|
exit 0 |
||||
|
else |
||||
|
err "Changing admin password in compose file not yet supported" |
||||
|
exit 1 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
if ! [ -d "$MATOMO_CODE/vendor" ]; then |
||||
|
|
||||
|
# XXXvlab: can't get real config here |
||||
|
if ! read-0 publish_dir_ts _ _ < <(get_service_relation "$SERVICE_NAME" "publish-dir"); then |
||||
|
err "Couldn't find relation ${DARKCYAN}publish-dir${NORMAL}." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
publish_dir_relation_dir=$(get_relation_data_dir "$SERVICE_NAME" "$publish_dir_ts" "publish-dir") || { |
||||
|
err "Failed to find relation file" |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
publish_dir_relation_config=$(cat "$publish_dir_relation_dir/data") || exit 2 |
||||
|
|
||||
|
domain=$(e "$publish_dir_relation_config" | shyaml get-value domain) || { |
||||
|
err "Couldn't get domain information in ${DARKCYAN}publish-dir${NORMAL} relation's data." |
||||
|
exit 1 |
||||
|
} |
||||
|
url=$(e "$publish_dir_relation_config" | shyaml get-value url) || { |
||||
|
err "Couldn't get url information in ${DARKCYAN}publish-dir${NORMAL} relation's data." |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## Get domain in option of relation "publish-dir" |
||||
|
## |
||||
|
|
||||
|
|
||||
|
container_id=$( |
||||
|
for container_id in $(get_running_containers_for_service "$MASTER_BASE_SERVICE_NAME"); do |
||||
|
e "$container_id" |
||||
|
break |
||||
|
done |
||||
|
) |
||||
|
|
||||
|
docker exec -i "$container_id" bash <<EOF |
||||
|
type -p "composer" || { |
||||
|
cd /tmp |
||||
|
curl -sS https://getcomposer.org/installer | php || { |
||||
|
echo "Error occured while attempting to install compose." >&2 |
||||
|
exit 1 |
||||
|
} |
||||
|
mv -v /tmp/composer.phar /usr/local/bin/composer || exit 1 |
||||
|
} |
||||
|
|
||||
|
cd /var/www/$domain && |
||||
|
composer install |
||||
|
|
||||
|
EOF |
||||
|
|
||||
|
fi |
||||
|
|
||||
|
|
||||
|
## |
||||
|
## Required wizard |
||||
|
## |
||||
|
|
||||
|
if [ "$(crudini --get "$MATOMO_CONFIG_FILE" General installation_in_progress)" == 1 ]; then |
||||
|
curl "$url/index.php?action=tablesCreation" >/dev/null || { |
||||
|
err "Table creation failed." |
||||
|
exit 1 |
||||
|
} |
||||
|
orig_uid_gid=$(stat --format=%u:%g "$MATOMO_CONFIG_FILE") |
||||
|
uid_gid=$(stat --format=%u:%g "$SERVICE_DATASTORE/var/tmp/matomo/index.php") |
||||
|
chown "$uid_gid" "$MATOMO_CONFIG_FILE" |
||||
|
curl "$url/index.php?action=setupSuperUser" \ |
||||
|
--data-urlencode login="admin" \ |
||||
|
--data-urlencode password="$admin_password" \ |
||||
|
--data-urlencode password_bis="$admin_password" \ |
||||
|
--data-urlencode email="${admin_email:-admin@localhost.localnet}" \ |
||||
|
--data-urlencode subscribe_newsletter_piwikorg="0" \ |
||||
|
--data-urlencode subscribe_newsletter_piwikpro="0" || { |
||||
|
err "Setting admin account failed." |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
chown "$orig_uid_gid" "$MATOMO_CONFIG_FILE" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" General installation_in_progress 0 |
||||
|
|
||||
|
#curl "$url/index.php?action=firstWebsiteSetup" \ |
||||
|
# --data-urlencode siteName="$SITE_NAME" \ |
||||
|
# --data-urlencode url="$url" \ |
||||
|
# --data-urlencode timezone="$(cat /etc/timezone)" \ |
||||
|
# --data-urlencode ecommerce="0" || { |
||||
|
# err "First Web Site Setup failed." |
||||
|
# exit 1 |
||||
|
#} |
||||
|
|
||||
|
fi |
||||
|
|
||||
|
|
||||
|
exit 0 |
@ -0,0 +1,77 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
. lib/common |
||||
|
|
||||
|
|
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
#domain=$(relation-get domain) || exit 1 |
||||
|
domain="matomo" |
||||
|
url=$(relation-get url) || exit 1 |
||||
|
# location=$CONFIGSTORE/$BASE_SERVICE_NAME/var/www/$domain |
||||
|
|
||||
|
upload_dir="${SERVICE_DATASTORE}/var/www/$domain/uploads" |
||||
|
if [ -d "$upload_dir" ]; then |
||||
|
uid_gid=$(stat --format=%u:%g "$upload_dir") |
||||
|
else |
||||
|
err "Upload dir '${upload_dir}' was not created. Can't continue." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
dirs=( |
||||
|
/var/cache/matomo |
||||
|
/var/lib/matomo{,/assets} |
||||
|
/var/log/matomo |
||||
|
/var/tmp/matomo{,/tcpdf,/templates_c} |
||||
|
) |
||||
|
|
||||
|
to_create=() |
||||
|
for dir in "${dirs[@]}"; do |
||||
|
fdir="${SERVICE_DATASTORE}${dir}" |
||||
|
if ! [ -d "$fdir" ]; then |
||||
|
to_create+=("$fdir") |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
if [ "${#to_create[@]}" -gt 0 ]; then |
||||
|
mkdir -p "${to_create[@]}" && |
||||
|
chown -v "$uid_gid" "${to_create[@]}" && |
||||
|
chmod -v g+rwx "${to_create[@]}" |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
|
||||
|
config-add " |
||||
|
services: |
||||
|
$MASTER_TARGET_SERVICE_NAME: |
||||
|
volumes: |
||||
|
- $SERVICE_DATASTORE/var/tmp/matomo:/var/www/$domain/tmp:rw |
||||
|
- $SERVICE_DATASTORE/var/cache/matomo:/var/www/$domain/tmp/cache:rw |
||||
|
- $SERVICE_DATASTORE/var/lib/matomo/assets:/var/www/$domain/tmp/assets:rw |
||||
|
- $SERVICE_DATASTORE/var/log/matomo:/var/www/$domain/tmp/logs:rw |
||||
|
- $SERVICE_DATASTORE/var/tmp/matomo/tcpdf:/var/www/$domain/tmp/tcpdf:rw |
||||
|
- $SERVICE_DATASTORE/var/tmp/matomo/templates_c:/var/www/$domain/tmp/templates_c:rw |
||||
|
" |
||||
|
|
||||
|
|
||||
|
# |
||||
|
#cat <<EOF >> "${MATOMO_CODE}"/.env |
||||
|
# |
||||
|
#BASE_PROTOCOL=${url%%://*} |
||||
|
#BASE_URL=$domain |
||||
|
#BASE_PATH=/index.php |
||||
|
# |
||||
|
#EOF |
||||
|
# |
||||
|
# |
||||
|
#cat <<EOF > "${MATOMO_CODE}"/web/.htaccess |
||||
|
# |
||||
|
#Options -MultiViews |
||||
|
#RewriteEngine On |
||||
|
#RewriteRule ^js/.* - [L] |
||||
|
#RewriteCond %{REQUEST_FILENAME} !-f |
||||
|
#RewriteRule ^(.*)$ index.php/\$1 [QSA,L] |
||||
|
# |
||||
|
#EOF |
||||
|
# |
@ -0,0 +1,95 @@ |
|||||
|
# -*- mode: shell-script -*- |
||||
|
|
||||
|
MATOMO_DIR="/opt/apps/matomo" |
||||
|
MATOMO_CODE="$SERVICE_CONFIGSTORE$MATOMO_DIR" |
||||
|
MATOMO_RELEASE=4.16.0 |
||||
|
MATOMO_URL=https://github.com/matomo-org/matomo/archive/"${MATOMO_RELEASE}".tar.gz |
||||
|
#MATOMO_URL=https://docker.0k.io/downloads/matomo-"${MATOMO_RELEASE}".tar.gz |
||||
|
MATOMO_CONFIG_FILE="${MATOMO_CODE}"/config/config.ini.php |
||||
|
|
||||
|
|
||||
|
matomo:init() { |
||||
|
current_version="" |
||||
|
if [ -d "${MATOMO_CODE}" ]; then |
||||
|
current_version=$(cat "${MATOMO_CODE}"/.version) || { |
||||
|
err "Couldn't find ${MATOMO_CODE}/.version file." |
||||
|
echo " Your config dir is in a broken state." >&2 |
||||
|
return 1 |
||||
|
} |
||||
|
else |
||||
|
mkdir -p "${MATOMO_CODE}" && |
||||
|
cd "${MATOMO_CODE}" && |
||||
|
git init . && |
||||
|
git config user.email "root@localhost" && |
||||
|
git config user.name "Root" || { |
||||
|
err "Couldn't create directory ${MATOMO_CODE}, or init it with git." |
||||
|
return 1 |
||||
|
} |
||||
|
fi |
||||
|
if [ "$current_version" != "$MATOMO_RELEASE" ]; then |
||||
|
cd "${MATOMO_CODE}" || return 1 |
||||
|
[ -d "$MATOMO_CODE"/.git ] || { |
||||
|
err "Can't find the '.git' directory in ${MATOMO_CODE}." |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
rm -rf "$MATOMO_CODE"/* "$MATOMO_CODE"/{.version,.inited-*} || return 1 |
||||
|
|
||||
|
curl -L "$MATOMO_URL" | tar xzv || { |
||||
|
#if [ -f "$MATOMO_URL" ]; then |
||||
|
# git checkout HEAD |
||||
|
#else |
||||
|
# rmdir "$MATOMO_URL" |
||||
|
#fi |
||||
|
err "Couldn't download $MATOMO_URL." |
||||
|
return 1 |
||||
|
} |
||||
|
mv matomo-*/* matomo-*/{.bowerrc,.lfsconfig} . && rmdir matomo-* |
||||
|
echo "$MATOMO_RELEASE" > .version |
||||
|
git add -A . && |
||||
|
git commit -m "Release $MATOMO_RELEASE" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
|
||||
|
matomo:config() { |
||||
|
[ -f "$MATOMO_CONFIG_FILE" ] || { |
||||
|
cat <<EOF > "$MATOMO_CONFIG_FILE" |
||||
|
; <?php exit; ?> DO NOT REMOVE THIS LINE |
||||
|
; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file. |
||||
|
EOF |
||||
|
} |
||||
|
crudini --get "$MATOMO_CONFIG_FILE" General salt >dev/null || { |
||||
|
salt=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | hexdump -v -e '/1 "%02x"') |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" General salt \"$salt\" |
||||
|
crudini --set "$MATOMO_CONFIG_FILE" General installation_in_progress 1 |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
matomo:curl() { |
||||
|
local url="$1" |
||||
|
curl "$url" |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
# matomo:wizard() { |
||||
|
|
||||
|
# PAGES=( |
||||
|
# "systemCheck" |
||||
|
# "databaseSetup" |
||||
|
# "tablesCreation" |
||||
|
# "setupSuperUser" |
||||
|
# "setupSuperUser" |
||||
|
# "firstWebsiteSetup" |
||||
|
# "firstWebsiteSetup" |
||||
|
# "trackingCode" |
||||
|
# "finished" |
||||
|
# ) |
||||
|
|
||||
|
# matomo:curl |
||||
|
|
||||
|
|
||||
|
# } |
@ -0,0 +1,45 @@ |
|||||
|
subordinate: true |
||||
|
requires: |
||||
|
web-publishing-directory: |
||||
|
interface: publish-dir |
||||
|
scope: container |
||||
|
default-options: |
||||
|
admin-password: admin |
||||
|
|
||||
|
|
||||
|
|
||||
|
uses: |
||||
|
publish-dir: |
||||
|
#constraint: required | recommended | optional |
||||
|
#auto: pair | summon | none ## default: pair |
||||
|
scope: container |
||||
|
constraint: required |
||||
|
auto: summon |
||||
|
solves: |
||||
|
container: "main running server" |
||||
|
default-options: |
||||
|
location: !var-expand "$CONFIGSTORE/$BASE_SERVICE_NAME/opt/apps/matomo" |
||||
|
data-dirs: ## write permission for web-app |
||||
|
- uploads |
||||
|
mysql-database: |
||||
|
#constraint: required | recommended | optional |
||||
|
#auto: pair | summon | none ## default: pair |
||||
|
constraint: required |
||||
|
auto: summon |
||||
|
solves: |
||||
|
database: "main storage" |
||||
|
backup: |
||||
|
constraint: recommended |
||||
|
auto: pair |
||||
|
solves: |
||||
|
backup: "Automatic regular backup" |
||||
|
default-options: |
||||
|
## First pattern matching wins, no pattern matching includes. |
||||
|
## include-patterns are checked first, then exclude-patterns |
||||
|
## Patterns rules: |
||||
|
## - ending / for directory |
||||
|
## - '*' authorized |
||||
|
## - must start with a '/', will start from $SERVICE_DATASTORE |
||||
|
exclude-patterns: |
||||
|
- "/var/cache/" |
||||
|
- "/var/tmp/" |
@ -0,0 +1,540 @@ |
|||||
|
#!/bin/bash |
||||
|
## compose: no-hooks |
||||
|
|
||||
|
|
||||
|
if [ -z "$SERVICE_DATASTORE" ]; then |
||||
|
echo "This script is meant to be run through 'compose' to work properly." >&2 |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
version=0.1 |
||||
|
usage="$exname [-h|--help] [--force|-f] [TARGET_VERSION]" |
||||
|
help=" |
||||
|
USAGE: |
||||
|
|
||||
|
$usage |
||||
|
|
||||
|
DESCRIPTION: |
||||
|
|
||||
|
Migrate the current $SERVICE_NAME service to given target version. Don't |
||||
|
forget to change your \`\`compose.yml\`\` accordingly afterwards. |
||||
|
|
||||
|
EXAMPLES: |
||||
|
|
||||
|
$exname 21.0.0 |
||||
|
|
||||
|
" |
||||
|
|
||||
|
no_hint= |
||||
|
force= |
||||
|
target= |
||||
|
while [ "$1" ]; do |
||||
|
case "$1" in |
||||
|
"--help"|"-h") |
||||
|
print_help >&2 |
||||
|
exit 0 |
||||
|
;; |
||||
|
"--force"|"-f") |
||||
|
force=yes |
||||
|
;; |
||||
|
"--color"|"-c") |
||||
|
ansi_color yes |
||||
|
;; |
||||
|
"--no-hint") |
||||
|
no_hint=yes |
||||
|
;; |
||||
|
--*|-*) |
||||
|
err "Unexpected optional argument '$1'" |
||||
|
print_usage >&2 |
||||
|
exit 1 |
||||
|
;; |
||||
|
*) |
||||
|
[ -z "$target" ] && { target=$1 ; shift ; continue ; } |
||||
|
err "Unexpected positional argument '$1'" |
||||
|
print_usage >&2 |
||||
|
exit 1 |
||||
|
;; |
||||
|
esac |
||||
|
shift |
||||
|
done |
||||
|
|
||||
|
postgres:image:version() { |
||||
|
local image="$1" image_version |
||||
|
## XXXvlab: why not always use the pragmatic second method ? |
||||
|
if [[ "${image}" =~ ^.*:[0-9]+.[0-9]+.[0-9]+$ ]]; then |
||||
|
debug "Infering postgres's version from image's name $image" |
||||
|
image_version="${image#*:}" |
||||
|
image_version="${image_version%-myc}" |
||||
|
else |
||||
|
debug "Looking for postgres's version in image $image" |
||||
|
if ! out=$(docker run --rm -i --entrypoint postgres "$image" --version); then |
||||
|
err "Couldn't infer image '$image' postgres's version." |
||||
|
exit 1 |
||||
|
fi |
||||
|
## Expected `$out` content of the form of: 'postgres (PostgreSQL) 10.14' |
||||
|
out=${out%%$'\n'*} |
||||
|
out=${out%%$'\r'*} |
||||
|
image_version=${out#"postgres (PostgreSQL) "}.0 |
||||
|
## check if this is a version |
||||
|
if ! [[ "$image_version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then |
||||
|
err "Couldn't infer image '$image' postgres's version: invalid version." |
||||
|
exit 1 |
||||
|
fi |
||||
|
fi |
||||
|
echo "$image_version" |
||||
|
} |
||||
|
|
||||
|
postgres:container:version() { |
||||
|
local container="$1" |
||||
|
if ! out=$(docker exec -i "$container" postgres --version); then |
||||
|
err "Couldn't infer container's '$container' postgres's version." |
||||
|
exit 1 |
||||
|
fi |
||||
|
out=${out%%$'\n'*} |
||||
|
out=${out%%$'\r'*} |
||||
|
image_version=${out#"postgres (PostgreSQL) "}.0 |
||||
|
## check if this is a version |
||||
|
if ! [[ "$image_version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then |
||||
|
err "Couldn't infer image '$image' postgres's version: invalid version '$image_version'." |
||||
|
exit 1 |
||||
|
fi |
||||
|
echo "$image_version" |
||||
|
} |
||||
|
|
||||
|
postgres:container:psql () { |
||||
|
local container="$1" |
||||
|
docker exec -i "$container" psql 2>&1 |
||||
|
} |
||||
|
|
||||
|
current_image_version=$(postgres:image:version "${DOCKER_BASE_IMAGE}") || exit 1 |
||||
|
if ! [[ "$current_image_version" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then |
||||
|
err "Current postgres version ${WHITE}$current_image_version${NORMAL} is unsupported yet." |
||||
|
exit 1 |
||||
|
fi |
||||
|
starting_image_version=$current_image_version |
||||
|
## This next line has to be on stdout, it is used by `vps` to get information |
||||
|
info "Current postgres version: ${WHITE}$current_image_version${NORMAL}" 2>&1 |
||||
|
|
||||
|
last_available_versions=( |
||||
|
$(DEBUG= docker:tags:fetch docker.0k.io/postgres 30 '[0-9]+\.[0-9]+\.[0-9]+-myc$' | |
||||
|
sed -r 's/-myc$//g' | |
||||
|
sort -rV) |
||||
|
) |
||||
|
|
||||
|
debug "Last available versions: ${WHITE}${last_available_versions[*]}${NORMAL}" |
||||
|
if [ -z "$target" ]; then |
||||
|
info "Latest version available: ${WHITE}${last_available_versions[0]}${NORMAL}" |
||||
|
fi |
||||
|
## XXXvlab: put this in kal-shlib-common |
||||
|
version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; } |
||||
|
|
||||
|
last_upgradable_versions=() |
||||
|
for v in "${last_available_versions[@]}"; do |
||||
|
if version_gt "$v" "$current_image_version"; then |
||||
|
last_upgradable_versions+=("$v") |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
if [ "${#last_upgradable_versions[@]}" == 0 ]; then |
||||
|
if [ -n "$target" ] && [ "$target" != "$current_image_version" ]; then |
||||
|
warn "Provided target version ${WHITE}$target${NORMAL} is likely incorrect." |
||||
|
echo " It is either non-existent and/or inferior to current version." >&2 |
||||
|
fi |
||||
|
## This next line has to be on stdout, it is used by `vps` to get information |
||||
|
info "${DARKYELLOW}postgres${NORMAL} is already ${GREEN}up-to-date${NORMAL}." 2>&1 |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$target" ]; then |
||||
|
info "Target latest version: ${WHITE}${last_upgradable_versions[0]}${NORMAL}" |
||||
|
target=${last_upgradable_versions[0]} |
||||
|
else |
||||
|
if [[ " ${last_available_versions[*]} " != *" $target "* ]]; then |
||||
|
err "Invalid version $target selected, please specify one of:" |
||||
|
for v in "${last_upgradable_versions[@]}"; do |
||||
|
echo " - $v" |
||||
|
done >&2 |
||||
|
exit 1 |
||||
|
fi |
||||
|
last_upgradable_versions_filtered=() |
||||
|
info "Target version ${WHITE}$target${NORMAL}" |
||||
|
for v in "${last_upgradable_versions[@]}"; do |
||||
|
if [ "$target" == "$v" ] || version_gt "$target" "$v"; then |
||||
|
last_upgradable_versions_filtered+=("$v") |
||||
|
fi |
||||
|
done |
||||
|
last_upgradable_versions=("${last_upgradable_versions_filtered[@]}") |
||||
|
fi |
||||
|
|
||||
|
debug "Last upgradable versions: ${WHITE}${last_upgradable_versions[*]}${NORMAL}" |
||||
|
|
||||
|
upgrade_path=($(printf "%s\n" "${last_upgradable_versions[@]}" | sort -V | tail -n 1)) |
||||
|
|
||||
|
containers="$(get_running_containers_for_service "$SERVICE_NAME")" |
||||
|
debug "Running containers for service $SERVICE_NAME: $containers" |
||||
|
debug "Upgrade path: ${WHITE}${upgrade_path[@]}${NORMAL}" |
||||
|
container_stopped=() |
||||
|
if [ -n "$containers" ]; then |
||||
|
#err "Running container(s) for $DARKYELLOW$SERVICE_NAME$NORMAL are still running:" |
||||
|
for container in $containers; do |
||||
|
debug "Stopping container $container" |
||||
|
docker stop "$container" >/dev/null || { |
||||
|
err "Failed to stop container '$container'." |
||||
|
exit 1 |
||||
|
} |
||||
|
## We need to delete it as otherwise, on final ``compose --debug up`` |
||||
|
## it won't be recreated, and it will not be the correct version. |
||||
|
docker rm "$container" > /dev/null || { |
||||
|
err "Couldn't delete container '$container'." |
||||
|
} |
||||
|
container_stopped+=("$container") |
||||
|
done |
||||
|
fi |
||||
|
|
||||
|
## XXXvlab: taking first container is probably not a good idea |
||||
|
container="$(echo "$containers" | head -n 1)" |
||||
|
|
||||
|
settmpdir MIGRATION_TMPDIR |
||||
|
debug "Migration temporary directory: $MIGRATION_TMPDIR" |
||||
|
set -o pipefail |
||||
|
|
||||
|
( |
||||
|
. "$CHARM_PATH/lib/common" |
||||
|
cp "$LOCAL_DB_PASSFILE" "$MIGRATION_TMPDIR/pgpass" |
||||
|
) |
||||
|
|
||||
|
|
||||
|
current_image="docker.0k.io/postgres:${current_image_version}-myc" |
||||
|
if ! docker_has_image "$current_image"; then |
||||
|
out=$(docker pull "$current_image" 2>&1) || { |
||||
|
err "Couldn't pull image $current_image:" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " >&2 |
||||
|
exit 1 |
||||
|
} |
||||
|
fi |
||||
|
|
||||
|
migration_backup_dirs=() |
||||
|
|
||||
|
## In postgres, it seems it is not useful to have a path. So path is |
||||
|
## only one step here. |
||||
|
|
||||
|
failed= |
||||
|
while [[ "${#upgrade_path[@]}" != 0 ]]; do |
||||
|
image_version="${upgrade_path[0]}" |
||||
|
|
||||
|
if version_gt "$image_version" 12; then |
||||
|
docker_version=$(docker info --format '{{.ServerVersion}}') |
||||
|
if ! version_gt "$docker_version" 20.10.0; then |
||||
|
err "Sorry, ${DARKYELLOW}$SERVICE_NAME${NORMAL} ${WHITE}$image_version${NORMAL}" \ |
||||
|
"require docker version >= 20.10 (current: $docker_version)" |
||||
|
break |
||||
|
fi |
||||
|
fi |
||||
|
upgrade_path=("${upgrade_path[@]:1}") |
||||
|
|
||||
|
## Prevent build of image instead of pulling it |
||||
|
|
||||
|
while true; do |
||||
|
|
||||
|
info "Upgrading step ${WHITE}$current_image_version${NORMAL} => ${WHITE}$image_version${NORMAL}" |
||||
|
rm -f "$MIGRATION_TMPDIR/dump-${current_image_version}.log" && |
||||
|
touch "$MIGRATION_TMPDIR/dump-${current_image_version}.log" |
||||
|
rm -f "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log" && |
||||
|
touch "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log" |
||||
|
uuid=$(openssl rand -hex 16) |
||||
|
|
||||
|
## Generate dump with pg_dumpall of current version: |
||||
|
|
||||
|
( |
||||
|
{ |
||||
|
cmd=( |
||||
|
compose --no-hooks |
||||
|
--add-compose-content="$SERVICE_NAME: |
||||
|
docker-compose: |
||||
|
image: docker.0k.io/postgres:${current_image_version}-myc |
||||
|
hostname: $SERVICE_NAME |
||||
|
" |
||||
|
run --rm --label "migration-uuid=$uuid" "$SERVICE_NAME" |
||||
|
) |
||||
|
echo COMMAND: "${cmd[@]}" |
||||
|
"${cmd[@]}" 2>&1 |
||||
|
echo "ERRORLEVEL: $?" |
||||
|
} | tee "$MIGRATION_TMPDIR/dump-${current_image_version}.log" >/dev/null |
||||
|
) & |
||||
|
pid="$!" |
||||
|
debug "Dumping container of $SERVICE_NAME in ${WHITE}$current_image_version${NORMAL}" \ |
||||
|
"launched with PID ${YELLOW}$pid${NORMAL}" |
||||
|
expected_stop="" |
||||
|
unexpected_stop="" |
||||
|
errlvl="" |
||||
|
while read -r line; do |
||||
|
case "$line" in |
||||
|
*" database system is ready to accept connections"*) |
||||
|
|
||||
|
migration_container=$(docker ps --filter "label=migration-uuid=$uuid" --format '{{.ID}}') |
||||
|
if [ -z "$migration_container" ]; then |
||||
|
err "Couldn't find migration container for $current_image_version" |
||||
|
echo " despite catched line stating postgres is listening." >&2 |
||||
|
break 3 |
||||
|
fi |
||||
|
## dump all |
||||
|
debug "Start dumping postgres database of ${WHITE}$current_image_version${NORMAL}" |
||||
|
if ! out=$( |
||||
|
{ |
||||
|
docker exec -u 70 "${migration_container}" pg_dumpall | |
||||
|
gzip > "$MIGRATION_TMPDIR/dump.sql.gz" |
||||
|
} 2>&1 ); then |
||||
|
err "Failed to dump postgres database." |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
unexpected_stop="1" |
||||
|
break |
||||
|
fi |
||||
|
|
||||
|
out=$(docker stop "$migration_container" 2>&1) || { |
||||
|
err "Failed to stop the dump container $migration_container for $current_image_version:" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
break 3 |
||||
|
} |
||||
|
expected_stop="1" |
||||
|
debug "Interrupting server process after dump (${YELLOW}$pid${NORMAL})" >&2 |
||||
|
kill "$pid" |
||||
|
errlvl="0" |
||||
|
break |
||||
|
;; |
||||
|
*"getaddrinfo(\"$SERVICE_NAME\") failed: Name or service not known"*) |
||||
|
err "Postgres issue with resolving '$SERVICE_NAME'" |
||||
|
failed=1 |
||||
|
break 3 |
||||
|
;; |
||||
|
"ERRORLEVEL: "*) |
||||
|
unexpected_stop="1" |
||||
|
errlvl="${line#ERRORLEVEL: }" |
||||
|
err "Unexpected stop of postgres dump container with errorlevel $errlvl" |
||||
|
break |
||||
|
;; |
||||
|
esac |
||||
|
done < <(tail -f "$MIGRATION_TMPDIR/dump-${current_image_version}.log") |
||||
|
[ "$unexpected_stop" == "1" ] && { |
||||
|
migration_container=$(docker ps --filter "label=migration-uuid=$uuid" --format '{{.ID}}') |
||||
|
if [ -n "$migration_container" ]; then |
||||
|
err "Stopping dumping docker container '$migration_container' after failure" |
||||
|
docker stop "$migration_container" >/dev/null 2>&1 || true |
||||
|
fi |
||||
|
failed=1 |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
[ "$expected_stop" == "1" ] && { |
||||
|
out=$(docker rmi "$current_image" 2>&1) || { |
||||
|
err "Failed to remove image $current_image" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
break 2 |
||||
|
} |
||||
|
} |
||||
|
next_image="docker.0k.io/postgres:${image_version}-myc" |
||||
|
if ! docker_has_image "$next_image"; then |
||||
|
out=$(docker pull "$next_image" 2>&1) || { |
||||
|
err "Couldn't pull image $next_image:" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " >&2 |
||||
|
unexpected_stop=1 |
||||
|
break 2 |
||||
|
} |
||||
|
fi |
||||
|
rm -f "$MIGRATION_TMPDIR/dump-${current_image_version}.log" |
||||
|
uuid=$(openssl rand -hex 16) |
||||
|
mv "$SERVICE_DATASTORE"{,".migration-${current_image_version}-${uuid}"} 2>&1 || { |
||||
|
err "Couldn't move datastore to backup location for $SERVICE_NAME" |
||||
|
unexpected_stop=1 |
||||
|
break 2 |
||||
|
} |
||||
|
migration_backup_dirs+=("$SERVICE_DATASTORE.migration-${current_image_version}-${uuid}") |
||||
|
( |
||||
|
{ |
||||
|
cmd=( |
||||
|
compose --debug |
||||
|
--add-compose-content="$SERVICE_NAME: |
||||
|
docker-compose: |
||||
|
image: docker.0k.io/postgres:${image_version}-myc |
||||
|
hostname: $SERVICE_NAME |
||||
|
" |
||||
|
run --rm --label "migration-uuid=$uuid" "$SERVICE_NAME" |
||||
|
) |
||||
|
echo COMMAND: "${cmd[@]}" |
||||
|
"${cmd[@]}" 2>&1 |
||||
|
echo "ERRORLEVEL: $?" |
||||
|
} | tee "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log" >/dev/null |
||||
|
) & |
||||
|
pid="$!" |
||||
|
debug "Migration launched with PID ${YELLOW}$pid${NORMAL}" |
||||
|
expected_stop="" |
||||
|
unexpected_stop="" |
||||
|
errlvl="" |
||||
|
while read -r line; do |
||||
|
case "$line" in |
||||
|
*" database system is ready to accept connections"*) |
||||
|
|
||||
|
migration_container=$(docker ps --filter "label=migration-uuid=$uuid" --format '{{.ID}}') |
||||
|
|
||||
|
## dump all |
||||
|
debug "Start restoring in postgres database ${WHITE}$current_image_version${NORMAL}" |
||||
|
if ! out=$( |
||||
|
{ |
||||
|
gunzip -c "$MIGRATION_TMPDIR/dump.sql.gz" | |
||||
|
docker exec -i -u 70 "${migration_container}" psql |
||||
|
} 2>&1 ); then |
||||
|
err "Failed to restore postgres database." |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
unexpected_stop="1" |
||||
|
break |
||||
|
fi |
||||
|
|
||||
|
current_image="$next_image" |
||||
|
current_image_version="$image_version" |
||||
|
out=$(docker stop "$migration_container" 2>&1) || { |
||||
|
err "Failed to stop the migration container $migration_container for $image_version:" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
break 3 |
||||
|
} |
||||
|
expected_stop="1" |
||||
|
debug "Interrupting server process after migration (${YELLOW}$pid${NORMAL})" >&2 |
||||
|
kill "$pid" |
||||
|
errlvl="0" |
||||
|
break |
||||
|
;; |
||||
|
*"getaddrinfo(\"$SERVICE_NAME\") failed: Name or service not known"*) |
||||
|
err "Postgres issue with resolving '$SERVICE_NAME'" |
||||
|
failed=1 |
||||
|
break 3 |
||||
|
;; |
||||
|
*"Replication has not yet been configured"*) |
||||
|
warn "Postgres was not setup right away, could lead to issues" |
||||
|
;; |
||||
|
"ERRORLEVEL: "*) |
||||
|
unexpected_stop="1" |
||||
|
errlvl="${line#ERRORLEVEL: }" |
||||
|
err "Unexpected stop of postgres migration container with errorlevel $errlvl" |
||||
|
failed=1 |
||||
|
break |
||||
|
;; |
||||
|
esac |
||||
|
done < <(tail -f "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log") |
||||
|
|
||||
|
[ "$unexpected_stop" == "1" ] && { |
||||
|
migration_container=$(docker ps --filter "label=migration-uuid=$uuid" --format '{{.ID}}') |
||||
|
if [ -n "$migration_container" ]; then |
||||
|
err "Stopping dumping docker container '$migration_container' after failure" |
||||
|
docker stop "$migration_container" >/dev/null 2>&1 || true |
||||
|
fi |
||||
|
failed=1 |
||||
|
break |
||||
|
} |
||||
|
|
||||
|
[ "$expected_stop" == "1" ] && { |
||||
|
continue 2 |
||||
|
} |
||||
|
|
||||
|
## |
||||
|
## Damage control, there are some things we can solve |
||||
|
## |
||||
|
|
||||
|
if grep "UPGRADE PROBLEM: Found an invalid featureCompatibilityVersion document" "$MIGRATION_TMPDIR/migration.log" >/dev/null 2>&1; then |
||||
|
if [ -z "$feature_comp" ]; then |
||||
|
feature_comp=1 |
||||
|
info "Detected featureCompatibilityVersion issue, forcing upgrade from base version" |
||||
|
echo " This will have for effect to reload the current version and set the featureCompatibilityVersion" >&2 |
||||
|
upgrade_path=("$current_image_version" "$image_version" "${upgrade_path[@]}") |
||||
|
break |
||||
|
else |
||||
|
err "Already tried to mitigate featureCompatibilityVersion without success..." |
||||
|
break 2 |
||||
|
fi |
||||
|
fi |
||||
|
err "Upgrade to ${WHITE}$image_version${NORMAL} ${DARKRED}failed${NORMAL}" |
||||
|
failed=1 |
||||
|
break 2 |
||||
|
done |
||||
|
|
||||
|
done |
||||
|
|
||||
|
if [ -z "$unexpected_stop" ] && [ -z "$expected_stop" ]; then |
||||
|
migration_container=$(docker ps --filter "label=migration-uuid=$uuid" --format '{{.ID}}') |
||||
|
if [ -n "$migration_container" ]; then |
||||
|
err "Stopping migration docker container '$migration_container' after failure" |
||||
|
docker stop "$migration_container" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
if [ -n "$failed" ]; then |
||||
|
if [ -e "$MIGRATION_TMPDIR/dump-${current_image_version}.log" ]; then |
||||
|
echo "${WHITE}Failing dump logs:${NORMAL}" >&2 |
||||
|
cat "$MIGRATION_TMPDIR/dump-${current_image_version}.log" | prefix " ${GRAY}|${NORMAL} " >&2 |
||||
|
fi |
||||
|
if [ -e "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log" ]; then |
||||
|
echo "${WHITE}Failing migration logs:${NORMAL}" >&2 |
||||
|
cat "$MIGRATION_TMPDIR/migration-${current_image_version}_${image_version}.log" | prefix " ${GRAY}|${NORMAL} " >&2 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
if [ -n "$unexpected_stop" ]; then |
||||
|
if [ -e "$SERVICE_DATASTORE.migration-${current_image_version}-${uuid}" ]; then |
||||
|
if [ -e "$SERVICE_DATASTORE" ]; then |
||||
|
mv -v "$SERVICE_DATASTORE"{,".migration-${image_version}-${uuid}-failed"} || { |
||||
|
err "Couldn't move back datastore to backup location for $SERVICE_NAME" |
||||
|
} |
||||
|
fi |
||||
|
mv -v "$SERVICE_DATASTORE"{".migration-${current_image_version}-${uuid}",} || { |
||||
|
err "Couldn't move back datastore to backup location for $SERVICE_NAME" |
||||
|
} |
||||
|
fi |
||||
|
err "Migration failed unexpectedly." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
if [ "$starting_image_version" == "$current_image_version" ]; then |
||||
|
warn "Database not migrated. Current version is still: ${WHITE}$current_image_version${NORMAL}" >&2 |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
( |
||||
|
. "$CHARM_PATH/lib/common" |
||||
|
cp "$MIGRATION_TMPDIR/pgpass" "$LOCAL_DB_PASSFILE" |
||||
|
) || { |
||||
|
err "Couldn't restore postgres password file." |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
for migration_backup_dir in "${migration_backup_dirs[@]}"; do |
||||
|
out=$(rm -rf "$migration_backup_dir") || { |
||||
|
warn "Couldn't remove backup directory $migration_backup_dir" |
||||
|
printf "%s\n" "$out" | prefix " ${GRAY}|${NORMAL} " |
||||
|
} |
||||
|
done |
||||
|
## This next line has to be on stdout, it is used by `vps` to get information |
||||
|
info "${GREEN}Successfully${NORMAL} upgraded from ${WHITE}$starting_image_version${NORMAL} to ${WHITE}$current_image_version${NORMAL}" 2>&1 |
||||
|
|
||||
|
|
||||
|
|
||||
|
if [ -z "$no_hint" ]; then |
||||
|
cat <<EOF >&2 |
||||
|
Don't forget to force the version in your \`\`compose.yml\`\`. For instance: |
||||
|
|
||||
|
${DARKYELLOW}$SERVICE_NAME${NORMAL}: |
||||
|
|
||||
|
${DARKGRAY}# ...${NORMAL} |
||||
|
|
||||
|
${WHITE}docker-compose${NORMAL}: |
||||
|
${WHITE}image${NORMAL}: docker.0k.io/postgres:${current_image_version}-myc |
||||
|
|
||||
|
${DARKGRAY}# ...${NORMAL} |
||||
|
|
||||
|
You could do this automatically with: |
||||
|
|
||||
|
yq eval -i ".$SERVICE_NAME.docker-compose.image = \"docker.0k.io/postgres:${current_image_version}-myc\" // \"\"" compose.yml |
||||
|
|
||||
|
And don't forget to run \`compose up\` afterwards. |
||||
|
|
||||
|
EOF |
||||
|
fi |
||||
|
|
||||
|
exit 0 |
@ -0,0 +1,18 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
OPTS=( |
||||
|
host |
||||
|
port |
||||
|
connection-security |
||||
|
auth-method |
||||
|
) |
||||
|
for var in "${OPTS[@]}"; do |
||||
|
value=$(options-get "$var") && relation-set "$var" "$value" || exit 1 |
||||
|
case "$var:$value" in |
||||
|
auth-method:password) |
||||
|
login=$(options-get "login") && relation-set login "$login" || exit 1 |
||||
|
password=$(options-get "password") && relation-set password "$password" || exit 1 |
||||
|
;; |
||||
|
esac |
||||
|
done |
||||
|
|
@ -0,0 +1,11 @@ |
|||||
|
type: stub |
||||
|
|
||||
|
provides: |
||||
|
smtp-server: |
||||
|
|
||||
|
default-options: |
||||
|
port: 25 |
||||
|
connection-security: none # "none", "starttls", "ssl/tls" |
||||
|
auth-method: plain # "none", "password" |
||||
|
user: |
||||
|
password: |
Write
Preview
Loading…
Cancel
Save
Reference in new issue