type: update
jpsVersion: 6.1.1
name: WordPress Backup/Restore for the filesystem and the databases
id: wp-backup
targetEditions: any
logo: /images/backup-logo.svg
description: Backup Add-On for the WordPress application root directory and the database. It can be used to create scheduled backups according to any required timezone and restore corrupted websites, even if the content has been completely deleted.
baseUrl: https://raw.githubusercontent.com/jelastic-jps/backup-addon/main
targetNodes:
nodeType:
- nginxphp
- litespeedphp
- lemp
- llsmp
settings:
main:
fields:
- type: radio-fieldset
name: scheduleType
hidden: false
default: '1'
values:
- value: 1
caption: Pre-defined
- value: 2
caption: Custom
- value: 3
caption: Manual (crontab)
tooltip: "A simple cron-based
scheduler to automatically start the backup process based on prescribed timing
instructions.
Note that the required timestamps should be specified
respectively to the UTC time zone.
"
showIf:
1:
- name: cronTime
caption: Backup schedule
type: list
editable: false
values:
- value: 0 * * * *
caption: "Hourly (at minute 0)"
- value: 0 0 * * *
caption: "Daily (at 00:00)"
- value: 0 0 * * 0
caption: "Weekly (at 00:00 on Sunday)"
- value: 0 0 1 * *
caption: "Monthly (at 00:00 on day 1)"
default: 0 0 * * *
2:
- type: string
name: backupTime
caption: Time
inputType: time
default: "09:00"
cls: x-form-text
width: 120
required: true
- caption: Days
type: compositefield
name: days
defaultMargins: 0 12 0 0
items:
- name: sun
value: true
type: checkbox
caption: Su
- name: mon
value: true
type: checkbox
caption: Mo
- name: tue
value: true
type: checkbox
caption: Tu
- name: wed
value: true
type: checkbox
caption: We
- name: thu
value: true
type: checkbox
caption: Th
- name: fri
value: true
type: checkbox
caption: Fr
- name: sat
value: true
type: checkbox
caption: Sa
- name: "tz"
caption: "Time Zone"
type: "list"
required: true
editable: true
forceSelection: true
values: values
3:
- name: cronTime
caption: Crontab
type: string
default: 0 0 * * *
regexText: Cron syntax is incorrect!
regex: "^(((([\\\\*]{1}){1,})|((\\\\*\\\\\\/){0,1}(([0-9\\/\\*\\-\\,]{1}){1,}|(([1-5]{1}){1}([0-9\\/\\*\\-\\,]{1}){1,}){1})))
((([\\\\*]{1}){1,})|((\\\\*\\\\\\/){0,1}(([0-9\\/\\*\\-\\,]{1}){1,}|(([1]{1}){1}([0-9\\/\\*\\-\\,-]{1}){1,}){1}|([2]{1}){1}([0-3]{1}){1})))
((([\\\\*]{1}){1})|((\\\\*\\\\\\/){0,1}(([1-9]{1}){1}|(([1-2]{1}){1}([0-9\\/\\*\\-\\,]{1}){1,5}){1}|([3]{1}){1}([0-1]{1}){1})))
((([\\\\*]{1}){1})|((\\\\*\\\\\\/){0,1}(([1-9]{1}){1}|(([1-2]{1}){1}([0-9\\/\\*\\-\\,]{1}){1,}){1}|([3]{1}){1}([0-1]{1}){1}))|(jan|JAN|feb|FEB|mar|MAR|apr|APR|may|MAY|jun|JUN|jul|JUL|aug|AUG|sep|SEP|okt|OKT|nov|NOV|dec|DEC)(-?\\w+?)?)
((([\\\\*]{1}){1})|((\\\\*\\\\\\/){0,1}(([0-7]{1,}(-?[0-7]?(,[0-7]){0,6})){1}))|((sun|SUN|mon|MON|tue|TUE|wed|WED|thu|THU|fri|FRI|sat|SAT)?(,(sun|SUN|mon|MON|tue|TUE|wed|WED|thu|THU|fri|FRI|sat|SAT)){0,6})(-?\\w+?)?))$|^(@(reboot|yearly|annualy|monthly|weekly|daily|hourly))$"
- caption: Backup storage
type: list
tooltip: "The environment with backup storage to be used for backups creation. Presence of this environment is obligatory."
name: storageName
dependsOn: region
required: true
- type: spinner
name: backupCount
caption: Number of backups
tooltip: "The number of newest backups to be kept during rotation."
min: 1
max: 30
default: 5
- type: toggle
name: isAlwaysUmount
caption: Always umount
tooltip: "Always unmount backup storage when backup/restore is finished."
value: false
hidden: false
onBeforeInit: scripts/configOnBeforeInit.js
restore:
fields: []
onBeforeInit: scripts/multipleRestoreOnBeforeInit.js
onBeforeInit: scripts/backupOnBeforeInit.js
buttons:
- caption: Backup Now
action: backup
loadingText: Backing up...
confirmText: Do you want to initiate the backup process?
successText: The backup process has been finished successfully.
- caption: Configure
action: configure
settings: main
loadingText: Configuring...
successText: The backup configs have been updated successfully.
- caption: Restore
action: restore
loadingText: Restoring...
settings: restore
successText: The backup have been successfully restored.
title: Restore Backup
submitButtonText: Restore
confirmText: You are going to restore from a backup, which will override all your existing data. This action cannot be canceled or reverted. Do you want to proceed?
globals:
scriptSufix: wp-backup
onInstall:
- checkApplication
- checkAddons
- installRestic
- setSchedule
onUninstall:
- callScript: uninstall
- removeScript
onBeforeDelete:
- callScript: uninstall
- removeScript
onAfterRedeployContainer[cp]:
- installRestic
onAfterClone:
- script: return {result:0, jps:MANIFEST};
- install: ${response.jps}
nodeGroup: ${targetNodes.nodeGroup:cp}
envName: ${event.response.env.envName}
settings:
scheduleType: ${settings.scheduleType}
storageName: ${settings.storageName}
cronTime: ${settings.cronTime}
backupTime: ${settings.backupTime}
sun: ${settings.sun}
mon: ${settings.mon}
tue: ${settings.tue}
wed: ${settings.wed}
thu: ${settings.thu}
fri: ${settings.fri}
sat: ${settings.sat}
tz: ${settings.tz}
backupCount: ${settings.backupCount}
isAlwaysUmount: ${settings.isAlwaysUmount}
onAfterConfirmTransfer: setSchedule
actions:
checkApplication:
- cmd[${nodes.cp.master.id}]: |-
[ -f /root/check_app.sh ] && rm -f /root/check_app.sh;
wget -O /root/check_app.sh ${baseUrl}/scripts/check_app.sh;
bash /root/check_app.sh;
user: root
- if (response.out == "Non-supported"):
- stopEvent:
type: warning
message: Deployed application is not supported by Backup add-on.
checkAddons:
- script: |-
var onAfterReturn = { setGlobals: {} },
glbs = onAfterReturn.setGlobals,
resp = api.marketplace.app.GetAddonList({
search: {},
envName: "${env.name}",
session: session
});
if (resp.result != 0) return resp;
glbs["alreadyInstalled"] = false;
for (let i = 0, n = resp.apps.length; i < n; i++) {
if (resp.apps[i].isInstalled) {
if (resp.apps[i].app_id == 'db-backup') {
glbs["alreadyInstalled"] = true;
break;
}
}
}
return { result: 0, onAfterReturn: onAfterReturn };
- if ('${globals.alreadyInstalled}' == 'true' ):
- stopEvent:
type: warning
message: Database backup add-on is already installed on ${env.name}. Backup addon installation is not possible.
installRestic:
cmd [cp]: |-
if which dnf; then
dnf install epel-release
dnf install restic
else
yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/copart/restic/repo/epel-7/copart-restic-epel-7.repo
yum-config-manager --enable copr:copr.fedorainfracloud.org:copart:restic
yum -y install restic
yum-config-manager --disable copr:copr.fedorainfracloud.org:copart:restic
wget -O /etc/logrotate.d/backup-addon ${baseUrl}/scripts/backup-addon;
fi
user: root
installScript:
- removeScript
- getStorageCtid
- script: ${baseUrl}/scripts/create-backup-main-script.js?_r=${fn.random}
params:
scriptName: ${env.envName}-${globals.scriptSufix}
baseUrl: ${baseUrl}
cronTime: ${this.cronTime}
backupCount: ${this.backupCount}
userId: ${env.uid}
storageNodeId: ${response.storageCtid}
backupExecNode: ${nodes.cp.master.id}
storageEnv: ${response.storageEnvShortName}
isAlwaysUmount: ${this.isAlwaysUmount}
callScript:
script: |-
var resp = api.dev.scripting.Eval(appid, session, '${env.envName}-${globals.scriptSufix}', {action:"${this}"});
if (resp.result === 1702 && "${this}" == "uninstall") {
return { result: 0, out: "script not found" };
} else {
return resp.response || resp;
}
removeScript:
script: |-
var resp = api.dev.scripting.GetScript(appid, session, '${env.envName}-${globals.scriptSufix}');
if (resp.result === 0) {
var resp = api.dev.scripting.DeleteScript(appid, session, '${env.envName}-${globals.scriptSufix}');
return resp.response || resp;
}
return { result: 0 };
backup:
- callScript: backup
- deleteDBdump
restore:
- cmd[cp]: |-
echo "${settings.backupedEnvName}" > /root/.backupedenv
echo "${settings.backupDir}" > /root/.backupid
user: root
- callScript: restore
- deleteDBdump
deleteDBdump:
- cmd[${targetNodes.nodeGroup}]: |-
[ -f /root/wp_db_backup.sql ] && rm -f /root/wp_db_backup.sql || exit 0;
user: root
configure:
- setSchedule
getStorageCtid:
- script: scripts/getStorageCtid.js
convert:
- script: |
var resp = {result:0, onAfterReturn: {setGlobals:{cron: ""}}}, offset = java.util.TimeZone.getTimeZone("${settings.tz}").getRawOffset(),
setGlobals = resp.onAfterReturn.setGlobals;
var time = "${settings.backupTime}".split(":"),
d1 = new Date(2020, 1, 10, parseInt(time[0],10), parseInt(time[1],10)),
d2 = new Date(d1.getTime() - offset),
dd = d2.getDate() - d1.getDate(),
days = getDays([${settings.sun:0}, ${settings.mon:0}, ${settings.tue:0}, ${settings.wed:0}, ${settings.thu:0}, ${settings.fri:0}, ${settings.sat:0}], dd);
setGlobals.cron = d2.getMinutes() + " " + d2.getHours() + " * * " + days.join(",");
function getDays(settings, dd) {
var days = [];
for (var i = 0, n = settings.length; i < n; i++) {
if (settings[i]) {
var day = i + dd;
if (day < 0) day +=7; else if (day > 6) day -=7;
days.push(day);
}
}
days.sort();
return days;
}
return resp;
setSchedule:
- setGlobals:
storageEnv: ${settings.storageName}
isAlwaysUmount: ${settings.isAlwaysUmount}
- if ("${settings.scheduleType}" == 2):
- convert
- else:
- setGlobals:
cron: ${settings.cronTime}
- if ("${settings.isAlwaysUmount}" == "true"):
- removePermanentMount
- else:
- removePermanentMount
- addPermanentMount
- installScript:
cronTime: ${globals.cron}
backupCount: ${settings.backupCount}
isAlwaysUmount: ${globals.isAlwaysUmount}
addPermanentMount:
- getStorageCtid
- script: |
return jelastic.env.file.AddMountPointById("${env.envName}", session, "${targetNodes.master.id}", "/opt/backup", "nfs4", null, "/data/", "${response.storageCtid}", "DBBackupRestore", false);
removePermanentMount:
- getStorageCtid
- script: |
var allMounts = jelastic.env.file.GetMountPoints("${env.envName}", session, "${targetNodes.master.id}").array;
for (var i = 0, n = allMounts.length; i < n; i++) {
if (allMounts[i].path == "/opt/backup" && allMounts[i].type == "INTERNAL") {
resp = jelastic.env.file.RemoveMountPointById("${env.envName}", session, "${targetNodes.master.id}", "/opt/backup");
if (resp.result != 0) { return resp; }
}
}
allMounts = jelastic.env.file.GetMountPoints("${env.envName}", session).array;
for (var i = 0, n = allMounts.length; i < n; i++) {
if (allMounts[i].path == "/opt/backup" && allMounts[i].type == "INTERNAL") {
resp = jelastic.env.file.RemoveMountPointByGroup("${env.envName}", session, "sqldb", "/opt/backup");
if (resp.result != 0) { return resp; }
}
}
return { "result": 0 };