Skip to content

Commit fe540ac

Browse files
authored
Merge pull request #165 from github/byodb-client-hooks
Run hooks for mysql backup/restore when external mysql database is configured
2 parents 6bdf349 + 9ec815e commit fe540ac

File tree

9 files changed

+139
-15
lines changed

9 files changed

+139
-15
lines changed

backup.config-example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,11 @@ GHE_NUM_SNAPSHOTS=10
7777
#
7878
# WARNING: this feature is in beta.
7979
#GHE_PARALLEL_MAX_LOAD=50
80+
81+
# When running an external mysql database, run this script to trigger a MySQL backup
82+
# rather than attempting to backup via backup-utils directly.
83+
#EXTERNAL_DATABASE_BACKUP_SCRIPT="/bin/false"
84+
85+
# When running an external mysql database, run this script to trigger a MySQL restore
86+
# rather than attempting to backup via backup-utils directly.
87+
#EXTERNAL_DATABASE_RESTORE_SCRIPT="/bin/false"

bin/ghe-backup

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,6 @@ ghe-ssh "$GHE_HOSTNAME" -- 'ghe-export-ssh-host-keys' > ssh-host-keys.tar ||
180180
failures="$failures ssh-host-keys"
181181
bm_end "ghe-export-ssh-host-keys"
182182

183-
if is_binary_backup_feature_on; then
184-
echo "Backing up MySQL database using binary backup strategy ..."
185-
else
186-
echo "Backing up MySQL database using logical backup strategy ..."
187-
fi
188183
ghe-backup-mysql || failures="$failures mysql"
189184

190185
commands=("

bin/ghe-restore

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -255,16 +255,21 @@ if [ -s "$GHE_RESTORE_SNAPSHOT_PATH/uuid" ] && ! $CLUSTER; then
255255
ghe-ssh "$GHE_HOSTNAME" -- "sudo rm -rf /data/user/consul/raft"
256256
fi
257257

258-
if is_binary_backup_feature_on; then
259-
appliance_strategy="binary"
260-
else
261-
appliance_strategy="logical"
262-
fi
258+
if is_service_external 'mysql' "$GHE_RESTORE_SNAPSHOT_PATH/settings.json"; then
259+
appliance_strategy="external"
260+
backup_snapshot_strategy="external"
261+
else
262+
if is_binary_backup_feature_on; then
263+
appliance_strategy="binary"
264+
else
265+
appliance_strategy="logical"
266+
fi
263267

264-
if is_binary_backup "$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT"; then
265-
backup_snapshot_strategy="binary"
266-
else
267-
backup_snapshot_strategy="logical"
268+
if is_binary_backup "$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT"; then
269+
backup_snapshot_strategy="binary"
270+
else
271+
backup_snapshot_strategy="logical"
272+
fi
268273
fi
269274

270275
echo "Restoring MySQL database from ${backup_snapshot_strategy} backup snapshot on an appliance configured for ${appliance_strategy} backups ..."

share/github-backup-utils/ghe-backup-config

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fi
152152
if [ ${GHE_DATA_DIR:0:1} != "/" ]; then
153153
GHE_DATA_DIR="$( cd "$GHE_BACKUP_ROOT" && readlink -m "$GHE_DATA_DIR" 2> /dev/null || echo "$GHE_BACKUP_ROOT/$GHE_DATA_DIR" )"
154154
fi
155+
export GHE_DATA_DIR
155156

156157
# Assign the Release File path if it hasn't been provided (eg: by test suite)
157158
: ${GHE_RELEASE_FILE:="/etc/github/enterprise-release"}
@@ -389,4 +390,22 @@ is_binary_backup_feature_on(){
389390
# Check if the backup is binary by looking up the sentinel file
390391
is_binary_backup(){
391392
test -f "$1/mysql-binary-backup-sentinel"
392-
}
393+
}
394+
395+
is_service_external(){
396+
service=$1
397+
config_file=$2
398+
case $service in
399+
"mysql")
400+
if [ -n "$config_file" ]; then
401+
enabled=$(GIT_CONFIG="$config_file" git config mysql.external.enabled)
402+
[ "$enabled" == "true" ];
403+
else
404+
ghe-ssh "$GHE_HOSTNAME" ghe-config --true "mysql.external.enabled"
405+
fi
406+
;;
407+
*)
408+
return 1
409+
;;
410+
esac
411+
}

share/github-backup-utils/ghe-backup-mysql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,26 @@ bm_start "$(basename $0)"
1515
# Perform a host-check and establish the remote version in GHE_REMOTE_VERSION.
1616
ghe_remote_version_required "$GHE_HOSTNAME"
1717

18+
if is_service_external 'mysql'; then
19+
echo "Backing up external MySQL database using customer-provided script..."
20+
if [ -n "$EXTERNAL_DATABASE_BACKUP_SCRIPT" ]; then
21+
$EXTERNAL_DATABASE_BACKUP_SCRIPT
22+
else
23+
echo "Error: EXTERNAL_DATABASE_BACKUP_SCRIPT is not configured. Please configure in backup.config."
24+
exit 1
25+
fi
26+
# Finsh the benchmark and exit early. If the script returns a non-zero
27+
# exit code, it will be caught by`set -e`
28+
bm_end "$(basename $0)"
29+
exit 0
30+
fi
31+
32+
if is_binary_backup_feature_on; then
33+
echo "Backing up MySQL database using binary backup strategy ..."
34+
else
35+
echo "Backing up MySQL database using logical backup strategy ..."
36+
fi
37+
1838
export_command="ghe-export-mysql"
1939
if ! is_binary_backup_feature_on; then
2040
# binary backup is already compressed

share/github-backup-utils/ghe-backup-settings

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ else
3535
unlink manage-password+
3636
fi
3737

38+
# Backup external MySQL password if running external MySQL DB.
39+
if is_service_external 'mysql'; then
40+
echo "Transferring external MySQL password..." 1>&3
41+
ghe-ssh "$host" -- ghe-config secrets.external.mysql > external-mysql-password+ || (
42+
echo "Warning: External MySQL password not set" >&2
43+
)
44+
if [ -n "$(cat external-mysql-password+)" ]; then
45+
mv external-mysql-password+ external-mysql-password
46+
else
47+
unlink external-mysql-password+
48+
fi
49+
fi
50+
3851
if ghe-ssh "$host" -- "test -f $GHE_REMOTE_DATA_USER_DIR/common/idp.crt"; then
3952
echo "* Transferring SAML keys ..." 1>&3
4053
ghe-ssh $host -- sudo tar -C $GHE_REMOTE_DATA_USER_DIR/common/ -cf - "idp.crt saml-sp.p12" > saml-keys.tar

share/github-backup-utils/ghe-restore-mysql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@ ghe_remote_version_required "$GHE_HOSTNAME"
2424
# The snapshot to restore should be set by the ghe-restore command but this lets
2525
# us run this script directly.
2626
: ${GHE_RESTORE_SNAPSHOT:=current}
27+
export GHE_RESTORE_SNAPSHOT
2728

2829
# The directory holding the snapshot to restore
2930
snapshot_dir="$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT"
3031

32+
# When customer uses external database, we rely on customer to implement the restore process
33+
if is_service_external 'mysql' "$snapshot_dir/settings.json"; then
34+
if [ -n "$EXTERNAL_DATABASE_RESTORE_SCRIPT" ]; then
35+
$EXTERNAL_DATABASE_RESTORE_SCRIPT
36+
else
37+
echo "Error: EXTERNAL_DATABASE_RESTORE_SCRIPT is not configured. Please configure in backup.config."
38+
exit 1
39+
fi
40+
# Finsh the benchmark and exit early. If the script returns a non-zero
41+
# exit code, it will be caught by`set -e`
42+
bm_end "$(basename $0)"
43+
exit 0
44+
fi
45+
3146
ssh_config_file_opt=
3247
if is_binary_backup_feature_on; then
3348
# Feature "mysql.backup.binary" is on, which means new backup scripts are available
@@ -84,6 +99,7 @@ ghe-ssh $ssh_config_file_opt "$GHE_RESTORE_HOST" -- "sudo mkdir -p '$GHE_REMOTE_
8499
# Transfer MySQL data from the snapshot to the GitHub instance.
85100
cat $snapshot_dir/mysql.sql.gz | ghe-ssh $ssh_config_file_opt "$GHE_RESTORE_HOST" -- "sudo dd of=$GHE_REMOTE_DATA_USER_DIR/tmp/mysql.sql.gz >/dev/null 2>&1"
86101

102+
echo "Restore MySQL database ..."
87103
# Import the database
88104
echo "cat $GHE_REMOTE_DATA_USER_DIR/tmp/mysql.sql.gz | $IMPORT_MYSQL" | ghe-ssh $ssh_config_file_opt "$GHE_RESTORE_HOST" -- /bin/bash 1>&3
89105

share/github-backup-utils/ghe-restore-settings

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ GHE_RESTORE_SNAPSHOT_PATH="$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT"
2828
echo "Restoring license ..."
2929
ghe-ssh "$GHE_HOSTNAME" -- 'ghe-import-license' < "$GHE_RESTORE_SNAPSHOT_PATH/enterprise.ghl" 1>&3
3030

31+
# Restore external MySQL password if running external MySQL DB.
32+
if [ -f "$GHE_RESTORE_SNAPSHOT_PATH/external-mysql-password" ]; then
33+
echo "Restoring external MySQL password ..."
34+
echo "ghe-config secrets.external.mysql '$(cat "$GHE_RESTORE_SNAPSHOT_PATH/external-mysql-password")'" |
35+
ghe-ssh "$GHE_HOSTNAME" -- /bin/bash
36+
fi
37+
3138
echo "Restoring settings ..."
3239
# work around issue importing settings with bad storage mode values
3340
( cat "$GHE_RESTORE_SNAPSHOT_PATH/settings.json" && echo ) |

test/test-ghe-backup-config.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,44 @@ begin_test "ghe-backup-config ghe_debug accepts stdin as well as argument"
184184
unset GHE_VERBOSE_LOG
185185
)
186186
end_test
187+
188+
begin_test "ghe-backup-config is_service_external enabled external mysql"
189+
(
190+
set -e
191+
192+
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
193+
echo "
194+
[mysql \"external\"]
195+
enabled = true
196+
" > $tmpfile
197+
is_service_external 'mysql' $tmpfile
198+
)
199+
end_test
200+
201+
begin_test "ghe-backup-config is_service_external disabled external mysql"
202+
(
203+
set -e
204+
205+
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
206+
echo "
207+
[mysql \"external\"]
208+
enabled = false
209+
" > $tmpfile
210+
211+
! is_service_external 'mysql' $tmpfile
212+
)
213+
end_test
214+
215+
begin_test "ghe-backup-config is_service_external unknown service"
216+
(
217+
set -e
218+
219+
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
220+
echo "
221+
[mysql \"external\"]
222+
enabled = false
223+
" > $tmpfile
224+
225+
! is_service_external 'hubot' $tmpfile
226+
)
227+
end_test

0 commit comments

Comments
 (0)