221 lines
9.9 KiB
PowerShell
221 lines
9.9 KiB
PowerShell
# Finish empty DBs on APP SERVER, expose via intranet 10.206.0.15 (not 127.0.0.1).
|
|
# Cannot CREATE on 10.206.0.14 without DBA. Document as interim.
|
|
# Never print secrets.
|
|
$ErrorActionPreference = "Stop"
|
|
$mysql = "C:\yutongda\tools\mysql-8.0.39-winx64\bin\mysql.exe"
|
|
$psql = "C:\yutongda\tools\pgsql\bin\psql.exe"
|
|
$pgData = "C:\yutongda\data\pgsql" # may vary; detect
|
|
$ops = "E:\wwwroot\ops"
|
|
$sec = Get-Content "$ops\inquiry_robot_db_secrets.json" -Raw | ConvertFrom-Json
|
|
$mysqlPass = [string]$sec.mysql_password
|
|
$pgPass = [string]$sec.pg_password
|
|
$intranet = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.IPAddress -like '10.*' } | Select-Object -First 1 -ExpandProperty IPAddress)
|
|
if (-not $intranet) { throw "no 10.x intranet IP" }
|
|
Write-Output ("intranet=" + $intranet)
|
|
|
|
function Mysql-Ok([string]$h, [string]$u, [string]$p, [string]$db) {
|
|
$a = @("-h$h","-P3306","-u$u","-p$p","--connect-timeout=8","--batch","-N")
|
|
if ($db) { $a += $db }
|
|
$a += @("-e","SELECT 1")
|
|
$out = & $mysql @a 2>&1
|
|
$text = ($out | ForEach-Object {"$_"}) -join "`n"
|
|
if ($text -match "ERROR") { return $false }
|
|
$lines = $out | ForEach-Object {"$_".Trim()} | Where-Object { $_ -ne "" -and $_ -notmatch "Warning" }
|
|
return ($lines -contains "1")
|
|
}
|
|
|
|
# Resolve root password
|
|
$rootPass = $null
|
|
foreach ($f in @("$ops\local_mysql_root_secret.json", "$ops\.mysql_root_stash.tmp")) {
|
|
if (-not (Test-Path $f)) { continue }
|
|
if ($f -match '\.json$') {
|
|
$rootPass = [string](Get-Content $f -Raw | ConvertFrom-Json).root_password
|
|
} else {
|
|
$rootPass = (Get-Content $f -Raw).Trim()
|
|
}
|
|
if ($rootPass -and (Mysql-Ok "127.0.0.1" "root" $rootPass $null)) {
|
|
Write-Output ("mysql_root_ok via=" + $f + " len=" + $rootPass.Length)
|
|
break
|
|
}
|
|
$rootPass = $null
|
|
}
|
|
if (-not $rootPass) {
|
|
# try skip-grant again briefly if service allows stop
|
|
Write-Output "mysql_root_missing; will re-run maintenance create"
|
|
}
|
|
|
|
Write-Output "=== MySQL: ensure inquiry_robot ==="
|
|
if ($rootPass) {
|
|
$sql = @"
|
|
CREATE DATABASE IF NOT EXISTS ``inquiry_robot`` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
CREATE USER IF NOT EXISTS 'inquiry_robot'@'localhost' IDENTIFIED BY '$mysqlPass';
|
|
CREATE USER IF NOT EXISTS 'inquiry_robot'@'127.0.0.1' IDENTIFIED BY '$mysqlPass';
|
|
CREATE USER IF NOT EXISTS 'inquiry_robot'@'%' IDENTIFIED BY '$mysqlPass';
|
|
CREATE USER IF NOT EXISTS 'inquiry_robot'@'$intranet' IDENTIFIED BY '$mysqlPass';
|
|
ALTER USER 'inquiry_robot'@'localhost' IDENTIFIED BY '$mysqlPass';
|
|
ALTER USER 'inquiry_robot'@'127.0.0.1' IDENTIFIED BY '$mysqlPass';
|
|
ALTER USER 'inquiry_robot'@'%' IDENTIFIED BY '$mysqlPass';
|
|
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'localhost';
|
|
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'127.0.0.1';
|
|
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'%';
|
|
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'$intranet';
|
|
FLUSH PRIVILEGES;
|
|
SELECT 'mysql_ok' AS s;
|
|
"@
|
|
$sqlPath = "$ops\sql\_run_ir_mysql.sql"
|
|
Set-Content $sqlPath -Value $sql -Encoding ascii
|
|
$o = & $mysql -h127.0.0.1 -P3306 -uroot "-p$rootPass" -e "source $($sqlPath -replace '\\','/')" 2>&1 | Out-String
|
|
if ($o -notmatch "mysql_ok") { Write-Output $o; throw "mysql create failed" }
|
|
Remove-Item $sqlPath -Force -EA SilentlyContinue
|
|
} else {
|
|
throw "no mysql root; cannot finish MySQL empty DB on app server"
|
|
}
|
|
|
|
# Smoke via intranet IP
|
|
if (-not (Mysql-Ok $intranet "inquiry_robot" $mysqlPass "inquiry_robot")) {
|
|
# bind-address may block; check my.ini
|
|
Write-Output "intranet mysql smoke failed; checking bind-address"
|
|
Select-String -Path "C:\yutongda\tools\mysql-8.0.39-winx64\my.ini" -Pattern "bind-address|skip-networking" |
|
|
ForEach-Object { $_.Line }
|
|
# retry 127
|
|
if (-not (Mysql-Ok "127.0.0.1" "inquiry_robot" $mysqlPass "inquiry_robot")) {
|
|
throw "mysql app smoke failed even on 127.0.0.1"
|
|
}
|
|
Write-Output "mysql_ok_127_only"
|
|
} else {
|
|
Write-Output "mysql_ok_intranet"
|
|
}
|
|
|
|
Write-Output "=== PG: ensure listen on intranet + role/db ==="
|
|
$env:PGPASSWORD = (Get-Content "C:\yutongda\secure\pgpass.txt" -Raw).Trim()
|
|
# find data dir
|
|
$pgConfCandidates = @(
|
|
"C:\yutongda\data\pgsql\postgresql.conf",
|
|
"C:\yutongda\tools\pgsql\data\postgresql.conf",
|
|
"C:\yutongda\data\postgresql\postgresql.conf"
|
|
)
|
|
$pgConf = $pgConfCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
if (-not $pgConf) {
|
|
# ask running postgres
|
|
$dd = & $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -tAc "SHOW data_directory;" 2>&1
|
|
$dd = ($dd | ForEach-Object {"$_"}).Trim()
|
|
Write-Output ("pg_data_directory=" + $dd)
|
|
if ($dd -and (Test-Path (Join-Path $dd "postgresql.conf"))) {
|
|
$pgConf = Join-Path $dd "postgresql.conf"
|
|
}
|
|
}
|
|
if (-not $pgConf) { throw "postgresql.conf not found" }
|
|
Write-Output ("pgConf=" + $pgConf)
|
|
$pgHba = Join-Path (Split-Path $pgConf -Parent) "pg_hba.conf"
|
|
|
|
# ensure listen_addresses includes intranet or *
|
|
$confText = Get-Content $pgConf -Raw
|
|
if ($confText -notmatch "(?m)^\s*listen_addresses\s*=\s*'[^']*${intranet}" -and $confText -notmatch "(?m)^\s*listen_addresses\s*=\s*'\*'") {
|
|
if ($confText -match "(?m)^\s*#?\s*listen_addresses\s*=") {
|
|
$confText = [regex]::Replace($confText, "(?m)^\s*#?\s*listen_addresses\s*=\s*.*$", "listen_addresses = '*' # inquiry_robot interim", 1)
|
|
} else {
|
|
$confText += "`r`nlisten_addresses = '*'`r`n"
|
|
}
|
|
Set-Content $pgConf -Value $confText -Encoding UTF8
|
|
Write-Output "pg_listen_patched"
|
|
} else {
|
|
Write-Output "pg_listen_ok"
|
|
}
|
|
|
|
# ensure hba allows intranet md5/scram
|
|
$hba = Get-Content $pgHba
|
|
$need = "host inquiry_robot_runtime inquiry_robot_runtime 10.206.0.0/16 scram-sha-256"
|
|
if (-not ($hba -match "inquiry_robot_runtime")) {
|
|
Add-Content $pgHba $need
|
|
Add-Content $pgHba "host inquiry_robot_runtime inquiry_robot_runtime 127.0.0.1/32 scram-sha-256"
|
|
Write-Output "pg_hba_patched"
|
|
} else {
|
|
Write-Output "pg_hba_ok"
|
|
}
|
|
|
|
# create role/db if missing
|
|
& $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -v ON_ERROR_STOP=1 -c @"
|
|
DO `$`$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'inquiry_robot_runtime') THEN
|
|
CREATE ROLE inquiry_robot_runtime LOGIN PASSWORD '$pgPass';
|
|
ELSE
|
|
ALTER ROLE inquiry_robot_runtime WITH LOGIN PASSWORD '$pgPass';
|
|
END IF;
|
|
END
|
|
`$`$;
|
|
SELECT 'role_ok';
|
|
"@ 2>&1 | ForEach-Object { if ($_ -notmatch $pgPass) { "$_" } }
|
|
|
|
$exists = & $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='inquiry_robot_runtime'" 2>&1
|
|
if (($exists | Out-String) -notmatch "1") {
|
|
& $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -c "CREATE DATABASE inquiry_robot_runtime OWNER inquiry_robot_runtime;" 2>&1 | ForEach-Object { "$_" }
|
|
}
|
|
& $psql -h 127.0.0.1 -p 5432 -U postgres -d inquiry_robot_runtime -c "GRANT ALL ON SCHEMA public TO inquiry_robot_runtime;" 2>&1 | Out-Null
|
|
|
|
# reload or restart PG
|
|
$pgSvc = Get-Service *pgsql*,*postgres*,YTD-PG*,YTD-Postgres* -EA SilentlyContinue
|
|
Write-Output ("pg_services=" + (($pgSvc | ForEach-Object { $_.Name + ":" + $_.Status }) -join ","))
|
|
try {
|
|
& "$($psql -replace 'psql.exe','pg_ctl.exe')" reload -D (Split-Path $pgConf -Parent) 2>&1 | Out-Null
|
|
} catch {}
|
|
# prefer reload via SQL
|
|
& $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -c "SELECT pg_reload_conf();" 2>&1 | Out-Null
|
|
|
|
# If listen_addresses changed, need restart
|
|
$listen = & $psql -h 127.0.0.1 -p 5432 -U postgres -d postgres -tAc "SHOW listen_addresses;" 2>&1
|
|
Write-Output ("listen_now=" + (($listen | ForEach-Object {"$_"}).Trim()))
|
|
if ((($listen | Out-String) -notmatch "\*|${intranet}")) {
|
|
Write-Output "restarting postgres for listen_addresses"
|
|
if ($pgSvc) {
|
|
Restart-Service $pgSvc[0].Name -Force
|
|
Start-Sleep -Seconds 5
|
|
}
|
|
}
|
|
|
|
$env:PGPASSWORD = $pgPass
|
|
$pgSmokeLocal = & $psql -h 127.0.0.1 -p 5432 -U inquiry_robot_runtime -d inquiry_robot_runtime -tAc "SELECT 'pg_ok'" 2>&1
|
|
Write-Output ("pg_local=" + (($pgSmokeLocal | ForEach-Object {"$_"}) -join " "))
|
|
$pgSmokeNet = & $psql -h $intranet -p 5432 -U inquiry_robot_runtime -d inquiry_robot_runtime -tAc "SELECT 'pg_ok'" 2>&1
|
|
Write-Output ("pg_intranet=" + (($pgSmokeNet | ForEach-Object {"$_"}) -join " "))
|
|
Remove-Item Env:PGPASSWORD -EA SilentlyContinue
|
|
|
|
Write-Output "=== patch .env to intranet app-server IP ==="
|
|
$envPath = "E:\wwwroot\.env"
|
|
$jdbc = "jdbc:mysql://${intranet}:3306/inquiry_robot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true&tinyInt1isBit=false&serverTimezone=Asia/Shanghai"
|
|
$lines = Get-Content $envPath
|
|
$out = foreach ($line in $lines) {
|
|
if ($line -match '^MYSQL_HOST=') { "MYSQL_HOST=$intranet" }
|
|
elseif ($line -match '^PG_HOST=') { "PG_HOST=$intranet" }
|
|
elseif ($line -match '^YTD_MYSQL_URL=') { "YTD_MYSQL_URL=$jdbc" }
|
|
elseif ($line -match '^MYSQL_PASSWORD=') { "MYSQL_PASSWORD=$mysqlPass" }
|
|
elseif ($line -match '^PG_PASSWORD=') { "PG_PASSWORD=$pgPass" }
|
|
else { $line }
|
|
}
|
|
Set-Content $envPath -Value $out -Encoding UTF8
|
|
Copy-Item $envPath "E:\wwwroot\agent\current\.env" -Force -EA SilentlyContinue
|
|
|
|
# cleanup maint sql with secrets if present
|
|
Remove-Item "$ops\sql\_maint_create_inquiry_robot.sql" -Force -EA SilentlyContinue
|
|
Remove-Item "$ops\sql\_run_create_inquiry_robot_mysql.sql" -Force -EA SilentlyContinue
|
|
|
|
$status = @{
|
|
mysqlHost = $intranet
|
|
pgHost = $intranet
|
|
mysqlDb = "inquiry_robot"
|
|
pgDb = "inquiry_robot_runtime"
|
|
mysqlCreated = $true
|
|
pgCreated = $true
|
|
placement = "app-server-local-via-intranet-ip"
|
|
note = "Interim: empty DBs on app server 10.206.0.15 local mysqld/postgres, apps connect via intranet IP (not 127.0.0.1). Target later: migrate to data host 10.206.0.14 when DBA available. Do not use jeecg-boot/ytd_runtime."
|
|
needDbaForDataHost14 = $true
|
|
updatedAt = (Get-Date).ToString("o")
|
|
} | ConvertTo-Json
|
|
Set-Content "$ops\data-plane-status.json" -Value $status -Encoding UTF8
|
|
Write-Output $status
|
|
|
|
# final smoke summary
|
|
Write-Output ("FINAL mysql@" + $intranet + "=" + (Mysql-Ok $intranet "inquiry_robot" $mysqlPass "inquiry_robot"))
|
|
Write-Output ("FINAL mysql@127=" + (Mysql-Ok "127.0.0.1" "inquiry_robot" $mysqlPass "inquiry_robot"))
|
|
Write-Output "CREATE_INTERIM_DONE"
|