|
| 1 | +<#PSScriptInfo |
| 2 | +.VERSION 1.1.0 |
| 3 | +.GUID 356b42ed-f2ab-47ed-af57-57a5411c3723 |
| 4 | +.AUTHOR Synopsys |
| 5 | +#> |
| 6 | + |
| 7 | +<# |
| 8 | +.DESCRIPTION |
| 9 | +This script automates the process of restoring the MariaDB master database with |
| 10 | +a logical backup generated by mysqldump: |
| 11 | +
|
| 12 | +mysqldump --host=127.0.0.1 --port=3306 --user=root -p codedx > /bitnami/mariadb/dump-codedx.sql |
| 13 | +
|
| 14 | +Note: This does not work with a physical backup generated with mariabackup. |
| 15 | +#> |
| 16 | + |
| 17 | +param ( |
| 18 | + [string] $backupToRestore, # logical backup file (dump.sql) or tar gzipped file (dump.tgz containing a dump.sql file) |
| 19 | + [string] $rootPwd, |
| 20 | + [string] $replicationPwd, |
| 21 | + [string] $namespace = 'cdx-app', |
| 22 | + [string] $releaseName = 'codedx', |
| 23 | + [int] $waitSeconds = 600, |
| 24 | + [switch] $skipWebRestart |
| 25 | +) |
| 26 | + |
| 27 | +$ErrorActionPreference = 'Stop' |
| 28 | +$VerbosePreference = 'Continue' |
| 29 | + |
| 30 | +Set-PSDebug -Strict |
| 31 | + |
| 32 | +$global:PSNativeCommandArgumentPassing='Legacy' |
| 33 | + |
| 34 | +'../.install-guided-setup-module.ps1' | ForEach-Object { |
| 35 | + $path = join-path $PSScriptRoot $_ |
| 36 | + if (-not (Test-Path $path)) { |
| 37 | + Write-Error "Unable to find file script dependency at $path. Please download the entire GitHub repository and rerun the downloaded copy of this script." |
| 38 | + } |
| 39 | + . $path |
| 40 | +} |
| 41 | + |
| 42 | +function New-DatabaseFromLogicalBackup([string] $namespace, |
| 43 | + [string] $podName, |
| 44 | + [string] $containerName, |
| 45 | + [string] $rootPwd, |
| 46 | + [string] $databaseName, |
| 47 | + [string] $databaseDump, |
| 48 | + [switch] $skipDropDatabase) { |
| 49 | + |
| 50 | + if (-not $skipDropDatabase) { |
| 51 | + Remove-Database $namespace $podName $containerName $rootPwd $databaseName |
| 52 | + } |
| 53 | + |
| 54 | + $cmd = "CREATE DATABASE $databaseName" |
| 55 | + |
| 56 | + kubectl -n $namespace exec -c $containerName $podName -- mysql -uroot --password=$rootPwd -e $cmd |
| 57 | + if (0 -ne $LASTEXITCODE) { |
| 58 | + Write-Error "Unable to create database, kubectl exited with exit code $LASTEXITCODE." |
| 59 | + } |
| 60 | + |
| 61 | + if (-not (Test-Path $databaseDump -PathType Leaf)) { |
| 62 | + Write-Error "Unable to find database dump file at $databaseDump." |
| 63 | + } |
| 64 | + |
| 65 | + $databaseDumpFilename = Split-Path $databaseDump -Leaf |
| 66 | + |
| 67 | + $importPath = "/bitnami/mariadb/$databaseDumpFilename" |
| 68 | + Copy-K8sItem $namespace $databaseDump $podName $containerName $importPath |
| 69 | + |
| 70 | + $databaseDumpFileExtension = [IO.Path]::GetExtension($databaseDumpFilename) |
| 71 | + if ($databaseDumpFileExtension -eq '.tgz') { |
| 72 | + |
| 73 | + # a tar gzip file should expand to a file of the same name with a .sql extension |
| 74 | + # for example, tar cvzf dump.tgz dump.sql |
| 75 | + kubectl -n $namespace exec -c $containerName $podName -- tar xvf $importPath -C '/bitnami/mariadb' |
| 76 | + if (0 -ne $LASTEXITCODE) { |
| 77 | + Write-Error "Unable to extract $importPath, kubectl exited with exit code $LASTEXITCODE." |
| 78 | + } |
| 79 | + $importPath = [IO.Path]::ChangeExtension($importPath, '.sql') |
| 80 | + } |
| 81 | + |
| 82 | + kubectl -n $namespace exec -c $containerName $podName -- bash -c "mysql -uroot --password=""$rootPwd"" $databaseName < $importPath" |
| 83 | + if (0 -ne $LASTEXITCODE) { |
| 84 | + Write-Error "Unable to import database dump, kubectl exited with exit code $LASTEXITCODE." |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +if (-not (Test-HelmRelease $namespace $releaseName)) { |
| 89 | + Write-Error "Unable to find Helm release named $releaseName in namespace $namespace." |
| 90 | +} |
| 91 | + |
| 92 | +$deployment = Get-HelmChartFullname $releaseName 'codedx' |
| 93 | +$statefulSetMariaDBMaster = "$releaseName-mariadb-master" |
| 94 | +$statefulSetMariaDBSlave = "$releaseName-mariadb-slave" |
| 95 | + |
| 96 | +$statefulSetMariaDBSlaveCount = (Get-HelmValues $namespace $releaseName).mariadb.slave.replicas |
| 97 | +if ($statefulSetMariaDBSlaveCount -eq 0) { |
| 98 | + $statefulSetMariaDBMaster = "$releaseName-mariadb" |
| 99 | + $statefulSetMariaDBSlave = '' |
| 100 | +} |
| 101 | + |
| 102 | +$mariaDbSecretName = "$releaseName-mariadb-pd" |
| 103 | +$mariaDbMasterServiceName = "$releaseName-mariadb" |
| 104 | + |
| 105 | +if (-not (Test-Deployment $namespace $deployment)) { |
| 106 | + Write-Error "Unable to find Deployment named $deployment in namespace $namespace." |
| 107 | +} |
| 108 | + |
| 109 | +if (-not (Test-StatefulSet $namespace $statefulSetMariaDBMaster)) { |
| 110 | + Write-Error "Unable to find StatefulSet named $statefulSetMariaDBMaster in namespace $namespace." |
| 111 | +} |
| 112 | + |
| 113 | +if ($statefulSetMariaDBSlaveCount -ne 0 -and (-not (Test-StatefulSet $namespace $statefulSetMariaDBSlave))) { |
| 114 | + Write-Error "Unable to find StatefulSet named $statefulSetMariaDBSlave in namespace $namespace." |
| 115 | +} |
| 116 | + |
| 117 | +if (-not (Test-Secret $namespace $mariaDbSecretName)) { |
| 118 | + # it could be a default DB resource |
| 119 | + Write-Error "Unable to find Secret named $mariaDbSecretName in namespace $namespace." |
| 120 | +} |
| 121 | + |
| 122 | +if (-not (Test-Service $namespace $mariaDbMasterServiceName)) { |
| 123 | + Write-Error "Unable to find Service named $mariaDbMasterServiceName in namespace $namespace." |
| 124 | +} |
| 125 | + |
| 126 | +$mariaDBServiceAccount = Get-ServiceAccountName $namespace 'statefulset' $statefulSetMariaDBMaster |
| 127 | + |
| 128 | +Write-Host @" |
| 129 | +
|
| 130 | +Using the following configuration: |
| 131 | +
|
| 132 | +Deployment Name: $deployment |
| 133 | +MariaDB Master StatefulSet Name: $statefulSetMariaDBMaster |
| 134 | +MariaDB Slave StatefulSet Name: $statefulSetMariaDBSlave |
| 135 | +MariaDB Slave Replica Count: $statefulSetMariaDBSlaveCount |
| 136 | +MariaDB Secret Name: $mariaDbSecretName |
| 137 | +MariaDB Master Service Name: $mariaDbMasterServiceName |
| 138 | +MariaDB Service Account: $mariaDBServiceAccount |
| 139 | +"@ |
| 140 | + |
| 141 | +if ($backupToRestore -eq '') { |
| 142 | + $backupToRestore = Read-HostText 'Enter the db backup to restore (backup.sql)' 1 |
| 143 | +} |
| 144 | + |
| 145 | +if (-not (Test-Path $backupToRestore -PathType Leaf)) { |
| 146 | + Write-Error "The '$backupToRestore' file does not exist." |
| 147 | +} |
| 148 | +if ('.sql','.tgz' -notcontains ([io.path]::GetExtension($backupToRestore))) { |
| 149 | + Write-Error "The '$backupToRestore' file does not have a .sql or .tgz file extension." |
| 150 | +} |
| 151 | +if ($backupToRestore.Contains(":")) { |
| 152 | + Write-Error "Unable to continue because the '$backupToRestore' path contains a colon that will disrupt a required kubectl cp command - specify an alternate, relative path instead." |
| 153 | +} |
| 154 | + |
| 155 | +if ($rootPwd -eq '') { |
| 156 | + $rootPwd = Read-HostSecureText 'Enter the password for the MariaDB root user' 1 |
| 157 | +} |
| 158 | + |
| 159 | +if ($replicationPwd -eq '') { |
| 160 | + $replicationPwd = Read-HostSecureText 'Enter the password for the MariaDB replication user' 1 |
| 161 | +} |
| 162 | + |
| 163 | +Write-Verbose 'Restarting database...' |
| 164 | +& (join-path $PSScriptRoot 'restart-db.ps1') -namespace $namespace -releaseName $releaseName -waitSeconds $waitSeconds -skipWebRestart |
| 165 | + |
| 166 | +Write-Verbose 'Searching for MariaDB slave pods...' |
| 167 | +$podFullNamesSlaves = kubectl -n $namespace get pod -l component=slave -o name |
| 168 | +if (0 -ne $LASTEXITCODE) { |
| 169 | + Write-Error "Unable to fetch slave pods, kubectl exited with exit code $LASTEXITCODE." |
| 170 | +} |
| 171 | + |
| 172 | +$podNamesSlaves = @() |
| 173 | +$podFullNamesSlaves | ForEach-Object { |
| 174 | + |
| 175 | + $podName = $_ -replace 'pod/','' |
| 176 | + $podNamesSlaves = $podNamesSlaves + $podName |
| 177 | +} |
| 178 | + |
| 179 | +Write-Verbose 'Searching for web pod...' |
| 180 | +$podName = kubectl -n $namespace get pod -l component=web -o name |
| 181 | +if (0 -ne $LASTEXITCODE) { |
| 182 | + Write-Error "Unable to find web pod, kubectl exited with exit code $LASTEXITCODE." |
| 183 | +} |
| 184 | +$podName = $podName -replace 'pod/','' |
| 185 | + |
| 186 | +Write-Verbose 'Searching for MariaDB master pod...' |
| 187 | +$podNameMaster = kubectl -n $namespace get pod -l component=master -o name |
| 188 | +if (0 -ne $LASTEXITCODE) { |
| 189 | + Write-Error "Unable to find MariaDB master pod, kubectl exited with exit code $LASTEXITCODE." |
| 190 | +} |
| 191 | + |
| 192 | +if ([string]::IsNullOrEmpty($podNameMaster)) { |
| 193 | + Write-Error "Unable to find primary database pod. Is it running?" |
| 194 | +} |
| 195 | +$podNameMaster = $podNameMaster -replace 'pod/','' |
| 196 | + |
| 197 | +Write-Verbose "Stopping deployment named $deployment..." |
| 198 | +Set-DeploymentReplicas $namespace $deployment 0 $waitSeconds |
| 199 | + |
| 200 | +Write-Verbose 'Stopping slave database instances...' |
| 201 | +$podNamesSlaves | ForEach-Object { |
| 202 | + Write-Verbose "Stopping slave named $_..." |
| 203 | + Stop-SlaveDB $namespace $_ 'mariadb' $rootPwd |
| 204 | +} |
| 205 | + |
| 206 | +Write-Verbose "Restoring database backup on pod $podNameMaster..." |
| 207 | +New-DatabaseFromLogicalBackup $namespace $podNameMaster 'mariadb' $rootPwd 'codedx' $backupToRestore |
| 208 | +$podNamesSlaves | ForEach-Object { |
| 209 | + Write-Verbose "Restoring database backup on pod $_..." |
| 210 | + New-DatabaseFromLogicalBackup $namespace $_ 'mariadb' $rootPwd 'codedx' $backupToRestore |
| 211 | +} |
| 212 | + |
| 213 | +Write-Verbose "Starting $statefulSetMariaDBMaster statefulset replica..." |
| 214 | +Set-StatefulSetReplicas $namespace $statefulSetMariaDBMaster 1 $waitSeconds |
| 215 | + |
| 216 | +if ($statefulSetMariaDBSlaveCount -ne 0) { |
| 217 | + |
| 218 | + Write-Verbose "Starting $statefulSetMariaDBSlave statefulset replica(s)..." |
| 219 | + Set-StatefulSetReplicas $namespace $statefulSetMariaDBSlave $statefulSetMariaDBSlaveCount $waitSeconds |
| 220 | + |
| 221 | + Write-Verbose 'Resetting master database...' |
| 222 | + $filePos = Get-MasterFilePosAfterReset $namespace 'mariadb' $podNameMaster $rootPwd |
| 223 | + |
| 224 | + Write-Verbose 'Connecting slave database(s)...' |
| 225 | + $podNamesSlaves | ForEach-Object { |
| 226 | + Write-Verbose "Restoring slave database pod $_..." |
| 227 | + Stop-SlaveDB $namespace $_ 'mariadb' $rootPwd |
| 228 | + Start-SlaveDB $namespace $_ 'mariadb' 'replicator' $replicationPwd $rootPwd $mariaDbMasterServiceName $filePos |
| 229 | + } |
| 230 | +} |
| 231 | + |
| 232 | +if ($skipWebRestart) { |
| 233 | + Write-Verbose "Skipping Restart..." |
| 234 | + Write-Verbose " To restart, run: kubectl -n $namespace scale --replicas=1 deployment/$deployment" |
| 235 | +} else { |
| 236 | + Write-Verbose "Starting deployment named $deployment..." |
| 237 | + Set-DeploymentReplicas $namespace $deployment 1 $waitSeconds |
| 238 | +} |
| 239 | + |
| 240 | +Write-Host 'Done' |
0 commit comments