1#!/usr/local/bin/bash 2 3set -e 4 5migration_command="puppetdb config-migration" 6 7############# 8# FUNCTIONS # 9############# 10 11# Display usage information and exit 12# 13# This function simply displays the usage information to the screen and exits 14# with exit code 0. 15# 16# Example: 17# 18# usage 19# 20function usage() { 21 echo "Usage: ${migration_command}" 22 echo "Configuration helper for migrating config files for PuppetDB upgrade." 23 echo 24 echo "This tool will attempt to copy the necessary PuppetDB config files into "\ 25 "place for use by the PuppetDB HTTPS service. It updates the pathing of "\ 26 "the files to align with new path expectations in the PuppetDB 3 series. "\ 27 "It will ensure the config files contain either existing edits or up "\ 28 "to date default settings. If the default settings are changed, the script "\ 29 "will also migrate any associated data into the new default location." 30 echo 31 echo "Options:" 32 echo " -h Help" 33 exit 0 34} 35 36# Backs up a file, if it hasn't already been backed up 37# 38# $1 - file to backup 39# 40# Example: 41# 42# backupfile "/etc/myconfig" 43# 44function backupfile { 45 # Create the global array if it doesn't already exist 46 if [ -z "$backupfile_list" ]; then 47 backupfile_list=() 48 fi 49 50 # We check the array to make sure the file isn't already backed up 51 if ! contains ${backupfile_list[@]} "$1"; then 52 local backup_path="$1.bak.$(date +%s)" 53 echo "Backing up $1 to ${backup_path} before making changes" 54 cp -p "$1" "$backup_path" 55 56 # Append to the array, so we don't need to back it up again later 57 backupfile_list+=($1) 58 fi 59} 60 61# This function searches for an element in an array returning 1 if it exists. 62# 63# $1 - array 64# $2 - item to search for 65# 66# Example: 67# 68# myarray=('element1', 'element2') 69# if contains ${myarray[@]}, "element1'; then 70# echo "element1 exists in the array" 71# fi 72# 73function contains { 74 local n=$# 75 local value=${!n} 76 for ((i=1;i < $#;i++)); do 77 if [ "${!i}" == "${value}" ]; then 78 return 0 79 fi 80 done 81 return 1 82} 83 84# This function wraps sed for a line focused search and replace. 85# 86# * Makes sure its atomic by writing to a temp file and moving it _after_ 87# * Escapes any forward slashes and ampersands on the RHS for you 88# 89# $1 - regexp to match 90# $2 - line to replace 91# $3 - file to operate on 92# 93# Example: 94# 95# replaceline "^$mysetting.*" "mysetting = myvalue" /etc/myconfig 96# 97function replaceline { 98 backupfile "$3" 99 tmp="$3.tmp.$(date +%s)" 100 sed "s/$1/$(echo "$2" | sed -e 's/[\/&]/\\&/g')/g" "$3" > "$tmp" 101 mv "$tmp" "$3" 102 chmod 644 "$3" 103} 104 105# This funtion gives a generic error message if a given path or file isn't found 106# 107# $1 - missing path 108# 109function path_not_found { 110 echo "Warning: Unable to find the path to copy" 111 echo 112 echo " This tool requires the following to exist:" 113 echo 114 echo " * $1" 115 echo 116 echo " Re-run this tool then restart PuppetDB to complete the config" 117 echo " setup:" 118 echo 119 echo " ${migration_command}" 120} 121 122 123# This function copies the give file to the given destination 124# 125# $1 - file or directory to be moved 126# $2 - destination 127# 128# Example: 129# 130# migrate_file "/etc/puppetdb/conf.d/config.ini" "/etc/puppetlabs/puppetdb/conf.d" 131# 132function migrate { 133 origin=$1 134 destination=$2 135 if [ "${destination##*/}" = "${origin##*/}" ] ; then 136 destination_path="${destination%/*}" 137 else 138 destination_path="$destination" 139 destination="${destination}/${origin##*/}" 140 fi 141 if [ ! -e "$origin" ]; then 142 path_not_found "$origin" 143 else 144 if [ -e "$destination" ] ; then 145 echo "Replacing: ${destination} with ${origin}" 146 cp -pr "$origin" "$destination_path" 147 else 148 echo "Copying: ${origin} to ${destination}" 149 mkdir -p "$destination_path" 150 cp -pr "$origin" "$destination_path" 151 fi 152 fi 153} 154 155######## 156# MAIN # 157######## 158 159# Gather command line options 160while getopts "h" opt; 161do 162 case $opt in 163 h) 164 usage ;; 165 *) 166 usage ;; 167 esac 168done 169 170 171# Figure out where the config files are we want to deal with 172# Either they exist in the archive created by the preinst script 173# during the upgrade, or the user is running this script by hand 174# and they exist in the PDB 2 series location 175if [ -e '/tmp/puppetdb-upgrade-config-files.tgz' ] ; then 176 orig_config_dir=/tmp/puppetdb-orig-configs 177 mkdir -p $orig_config_dir 178 tar -xzf '/tmp/puppetdb-upgrade-config-files.tgz' -C $orig_config_dir 179elif [ -e '/etc/puppetdb/conf.d/config.ini' -a -e '/etc/puppetdb/conf.d/database.ini' -a -e '/etc/puppetdb/conf.d/jetty.ini' ] ; then 180 orig_config_dir=/etc/puppetdb/conf.d 181else 182 echo "Config archive not found. Not proceeding with migration" 183 exit 0 184fi 185 186orig_jetty_file=${orig_config_dir}/jetty.ini 187orig_database_file=${orig_config_dir}/database.ini 188orig_config_file=${orig_config_dir}/config.ini 189orig_ini_files=($orig_jetty_file $orig_database_file $orig_config_file) 190 191config_dir=/etc/puppetlabs/puppetdb/conf.d 192database_file=${config_dir}/database.ini 193jetty_file=${config_dir}/jetty.ini 194config_file=${config_dir}/config.ini 195ini_files=($config_file $jetty_file $database_file) 196 197 198echo "Migrating configuration files ${orig_ini_files[*]} to ${config_dir}" 199for orig_ini_file in "${orig_ini_files[@]}" ; do 200 migrate "$orig_ini_file" "$config_dir" 201done 202 203echo "Checking to see if we need to update default settings" 204for ini_file in "${ini_files[@]}"; do 205 if [ -f "${ini_file}" ] ; then 206 207 # Check settings are correct and fix or warn. Do not move vardir behind 208 # subname. 209 orig_settings=( 210 "vardir:/var/lib/puppetdb" 211 "logging-config:/etc/puppetdb/logback.xml" 212 "subname:file:/var/lib/puppetdb/db/db;hsqldb.tx=mvcc;sql.syntax_pgs=true" 213 "ssl-key:/etc/puppetdb/ssl/private.pem" 214 "ssl-cert:/etc/puppetdb/ssl/public.pem" 215 "ssl-ca-cert:/etc/puppetdb/ssl/ca.pem" 216 ) 217 new_settings=( 218 "vardir:/opt/puppetlabs/server/data/puppetdb" 219 "logging-config:/etc/puppetlabs/puppetdb/logback.xml" 220 "subname:file:/opt/puppetlabs/server/data/puppetdb/db/db;hsqldb.tx=mvcc;sql.syntax_pgs=true" 221 "ssl-key:/etc/puppetlabs/puppetdb/ssl/private.pem" 222 "ssl-cert:/etc/puppetlabs/puppetdb/ssl/public.pem" 223 "ssl-ca-cert:/etc/puppetlabs/puppetdb/ssl/ca.pem" 224 ) 225 226 for i in "${orig_settings[@]}"; do 227 setting="${i%%:*}" 228 orig_value="${i#*:}" 229 for j in "${new_settings[@]}"; do 230 if [ "${j%%:*}" == "${setting}" ] ; then 231 new_value="${j#*:}" 232 if grep -qe "^${setting}" "$ini_file"; then 233 if grep -qe "^${setting}[[:space:]]*=[[:space:]]*${orig_value}$" "$ini_file"; then 234 replaceline "^${setting}.*" "${setting} = ${new_value}" "$ini_file" 235 echo "Updated setting ${setting} in ${ini_file}." 236 case "$setting" in 237 vardir|ssl-*) 238 migrate "$orig_value" "$new_value" 239 rm -rf "$orig_value" 240 ;; 241 subname) 242 orig_hsql_path="${orig_value#file:}" 243 orig_hsql_dir="${orig_hsql_path%/db;hsqldb.tx=mvcc;sql.syntax_pgs=true}" 244 new_hsql_path="${new_value#file:}" 245 new_hsql_dir="${new_hsql_path%/db;hsqldb.tx=mvcc;sql.syntax_pgs=true}" 246 ## if the default vardir still exists, then the vardir was 247 ## changed, but the subname still points to the default 248 ## vardir. 249 if [ -e "$orig_hsql_dir" ] ; then 250 echo "Copying over the contents of ${orig_hsql_dir} to ${new_hsql_dir}" 251 migrate "$orig_hsql_dir" "$new_hsql_dir" 252 rm -rf "$orig_hsql_dir" 253 fi 254 ;; 255 esac 256 else 257 echo "Setting ${setting} in ${ini_file} has been changed from the default, so will not be updated." 258 fi 259 else 260 if grep -qE "^# ?${setting} = <[A-Za-z_]+>$" "$ini_file"; then 261 replaceline "^# ?${setting}.*" "${setting} = ${new_value}" "$ini_file" 262 echo "Updated default settings from package installation for ${setting} in ${ini_file}." 263 fi 264 fi 265 fi 266 done 267 done 268 else 269 echo "Error: Unable to find PuppetDB configuration file at ${ini_file} so unable to provide automatic configuration for that file." 270 echo 271 echo " Confirm the file exists before running the tool again." 272 echo " The file should have been created automatically when" 273 echo " the package was installed." 274 fi 275done 276echo "cleaning up old config files" 277old_config_dir=/etc/puppetdb/conf.d 278old_jetty_file=${old_config_dir}/jetty.ini 279old_database_file=${old_config_dir}/database.ini 280old_config_file=${old_config_dir}/config.ini 281old_ini_files=($old_jetty_file $old_database_file $old_config_file) 282 283for old_ini_file in "${old_ini_files[@]}" ; do 284 if [ -e "$old_ini_file" ] ; then 285 echo "Removing $old_ini_file" 286 rm "$old_ini_file" 287 fi 288 if [ -e "${old_ini_file}.rpmsave" ] ; then 289 echo "Removing ${old_ini_file}.rpmsave" 290 rm "${old_ini_file}.rpmsave" 291 fi 292done 293 294echo "Modifications may have been made to PuppetDB config files. To ensure these changes have been picked up, please do the following: " 295echo " 1) upgrade the puppetdb-termini package" 296echo " 2) restart the puppetdb service" 297echo " 3) restart the puppetserver service" 298