Automating Bamboo backup operations
Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.
Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
Bamboo supports two methods of taking a backup of the instance, which can be manual or scheduled backup, as explained in Exporting data for backup. The following script provides an example of an alternative method via a script that takes a dump of the native database. This is particularly useful when the instance is large, and the Bamboo XML backup functionality is slow.
Solution
This script should be used as a guide on what steps should be taken to proceed with an external backup of Bamboo. Each customer is expected to have particular requirements, and changes to this script might be necessary.
If you are using AWS Backup technology, please check the following KB article for specific recommendations regarding that technology adoption and Bamboo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/bin/bash
#
# Bamboo Backup script
#
# THIS IS NOT PLUG AND PLAY. YOU NEED TO READ THIS SCRIPT
# AND ADAPT IT TO YOUR VERY REQUIREMENTS
#
# This script should be used as a guide on what steps should be taken to proceed
# with an external backup of Bamboo. It is expected that each customer may have
# particular requirements and changes to this script might be necessary
#
# This script will:
# * Pause your Bamboo instance
# * Sync your Bamboo home contents to a backup location
# * Dump your MySQL/PostgreSQL/Favorite database
# * Resume your Bamboo instance
# Requirements:
# * rsync
# * curl
# * python
# * mysqldump or pg_dump (or any DB_dump tool you require)
# * bamboo admin account credentials or a PAT (see below)
# Usage:
# Adjust any variables within the # VARIABLES block
# Run it from the command line or cron
#
# VARIABLES
#
curl="/usr/bin/curl -s -k"
rsync="/usr/bin/rsync -a --numeric-ids --sparse --delete"
backup_dir="/path/to/backup/directory"
backup_sql="${backup_dir}/bamboo_database.sql"
bamboo_home="/path/to/bamboo_home"
bamboo_url="http://localhost:10572/bamboo572"
url="${bamboo_url}/rest/api/latest/server"
verbose=1
# Define the authentication method: token, or user and password
# We are using auth="userpass" by default
# If you prefer to use a Personal Authentication Token (PAT), define auth="token"
# https://confluence.atlassian.com/bamboo/personal-access-tokens-976779873.html
auth="userpass"
#auth="token"
username="admin"
password="admin"
token="XXXXXYYYYYZZZZZZAAAAAABBBBBBCCCCCC"
# Define the number of times and the interval between each state check
# Once a request for a PAUSED state is issued, Bamboo will remain in a
# PAUSING state until all jobs are completed before declaring itself
# as PAUSED
# * Default: Tries=60, Interval=30 (s) = Total 30m
getStateTries=60
getStateInterval=30
# Try to revert to the initial Bamboo state if the script fails. Recommended
revertIfFail=1
#
# END OF VARIABLES
#
# -e will make this script fail on first error
set -e
# Print verbose logs
verbose() {
((verbose)) && printf " ==> $*\n"
}
# Export the authentication method to curl
case $auth in
userpass)
verbose "_CURL_AUTH=userpass"
_CURL_AUTH="-u ${username}:${password}"
;;
token)
verbose "_CURL_AUTH=token"
_CURL_AUTH="-H \"Authorization: Bearer ${token}\""
;;
*)
echo "You must set \$auth to either \"userpass\" or \"token\""
;;
esac
# Get the current state of Bamboo
getState() {
${curl} -H "Content-Type:application/json" -H "Accept:application/json" \
${_CURL_AUTH} -X GET ${url} 2>/dev/null \
| python -c 'import json,sys;print json.load(sys.stdin)["state"]'
}
# Define vars and actions according to the state
defineState() {
case $1 in
resume|RUNNING)
api_state="RUNNING" && action="resume" && revert="pause" ;;
pause|PAUSING|PAUSED)
api_state="PAUSED" && action="pause" && revert="resume" ;;
esac
}
# Wait for a State to be present
# Uses a combination of $getStateTries and $getStateInterval
waitforState() {
# ARG1 is the desired state RUNNING / PAUSED
# ARG2 is the timeout (1 sec interval)
trap 'return 1' SIGINT SIGTERM
max_retry=$2
counter=1
defineState $1
verbose "Expected state: ${api_state^^}"
until (getState | grep -q ${api_state^^}) ; do
sleep ${getStateInterval}
[[ ${counter} = ${max_retry} ]] && echo "State check failed" && return 1
echo "Waiting for ${api_state^^} state. Trying again. #${counter}"
((counter++))
done
verbose "Acquired state: $(getState)"
}
# Modifies Bamboo state
setState() {
# ARG1 is the desired state RUNNING / PAUSED
new_state=$1
curr_state="$(getState)"
verbose "Current state: ${curr_state}"
callsetState() {
defineState $1
if [ "$2" = "revert" ] ; then
_target="${url}/${revert}?os_authType=basic"
else
_target="${url}/${action}?os_authType=basic"
fi
verbose "Running ${curl} ***masked*** -X \"${_target}\""
eval $(echo ${curl} ${_CURL_AUTH} -X POST -o /dev/null ${_target})
}
verbose "Sending API call state to ${new_state} Bamboo"
callsetState ${new_state}
verbose "Calling waitforState ${new_state} ${getStateTries}"
waitforState ${new_state} ${getStateTries} || \
( ((revertIfFail)) \
&& echo "Failed to set state to ${new_state}. Reverting state" \
&& echo "Current state: $(getState)" \
&& callsetState ${new_state} revert \
&& waitforState ${curr_state} ${getStateTries} \
&& return 1)
}
# Collect Original state before anything
INITIAL_STATE=$(getState)
verbose "Initial state is: ${INITIAL_STATE}"
# Pause server with validation
# Will try to set Bamboo into a PAUSED state
# It will try up (getStateTries x getStateInterval)
echo "Starting Bamboo backup: $(date)"
verbose "Calling Bamboo setState pause"
setState pause && GOOD_TO_BACKUP=1
if [ ${GOOD_TO_BACKUP} ] ; then
echo "Bamboo was set to a PAUSED state. Proceeding with FS/DB Backup"
# Backup Bamboo home
# It excludes the artifact folder
# You may remove this exclusion but your backup size and time may increase considerably
verbose "Calling Filesystem backup process"
${rsync} --exclude=build-dir --exclude=build_logs --exclude=artifacts ${bamboo_home} ${backup_dir}
# Dump the database contents
# Replace with the database user
# Make sure your backup command works non-interactively (no confirmations/password
# prompts). Some databases require ACLs to be set. Make sure it allows the script to
# dump the DB.
# Validate the command manually before using it with in the script
verbose "Calling DB backup process"
#pg_dump -U postgres -h localhost > ${backup_sql}
mysqldump -uroot -proot bamboo > ${backup_sql}
# Resume Bamboo
# Puts Bamboo in a RUNNING state
verbose "Calling Bamboo setState resume"
setState resume && echo "Bamboo was set to a RUNNING state. Backup finished successfully"
else
echo "There was an issue with the backup. Exiting"
exit 1
fi
The above script can be adapted based on the native database backup tool. In this case, we were using MySQL.
Was this helpful?