初始化询价智能体新仓:同步本地工程并排除密钥与 .env。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
# Provision Redis + MinIO (bucket inquiry-robot) + MySQL/PG SQL prep
|
||||
$ErrorActionPreference = "Continue"
|
||||
$Root = "E:\wwwroot"
|
||||
$Ops = Join-Path $Root "ops"
|
||||
$SqlDir = Join-Path $Ops "sql"
|
||||
New-Item -ItemType Directory -Force -Path $Ops, $SqlDir | Out-Null
|
||||
$Bucket = "inquiry-robot" # S3: no underscore
|
||||
|
||||
function New-Secret([int]$len = 48) {
|
||||
$bytes = New-Object byte[] $len
|
||||
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
|
||||
return ([Convert]::ToBase64String($bytes) -replace '[+/=]', 'x').Substring(0, [Math]::Min(64, $len))
|
||||
}
|
||||
|
||||
function Upsert-Env([string]$path, [hashtable]$pairs) {
|
||||
$lines = @()
|
||||
if (Test-Path $path) { $lines = @(Get-Content $path) }
|
||||
$out = New-Object System.Collections.Generic.List[string]
|
||||
$seen = @{}
|
||||
foreach ($line in $lines) {
|
||||
if ($line -match '^\s*#' -or $line -notmatch '=' -or [string]::IsNullOrWhiteSpace($line)) {
|
||||
[void]$out.Add($line)
|
||||
continue
|
||||
}
|
||||
$k = ($line.Split('=', 2))[0]
|
||||
if ($pairs.ContainsKey($k)) {
|
||||
[void]$out.Add("$k=$($pairs[$k])")
|
||||
$seen[$k] = $true
|
||||
} else {
|
||||
[void]$out.Add($line)
|
||||
$seen[$k] = $true
|
||||
}
|
||||
}
|
||||
foreach ($k in $pairs.Keys) {
|
||||
if (-not $seen.ContainsKey($k)) { [void]$out.Add("$k=$($pairs[$k])") }
|
||||
}
|
||||
Set-Content -Path $path -Value $out.ToArray() -Encoding UTF8
|
||||
}
|
||||
|
||||
Write-Output "=== Redis ==="
|
||||
$redisCred = Get-Content "C:\yutongda\secure\redis-credentials.json" -Raw | ConvertFrom-Json
|
||||
$rcli = "C:\yutongda\tools\redis-5.0.14.1\redis-cli.exe"
|
||||
$redisScript = "AUTH $($redisCred.application_username) $($redisCred.application_password)`nSELECT 1`nPING`nSET inquiry_robot:provision:ping ok EX 300`nGET inquiry_robot:provision:ping`nQUIT`n"
|
||||
$redisOut = $redisScript | & $rcli -h $redisCred.host -p $redisCred.port 2>&1
|
||||
$joined = ($redisOut | ForEach-Object { "$_" }) -join "`n"
|
||||
if ($joined -notmatch 'PONG') { Write-Output $joined; throw "redis ping failed" }
|
||||
Write-Output "REDIS_OK"
|
||||
$redisUrl = "redis://$($redisCred.application_username):$($redisCred.application_password)@$($redisCred.host):$($redisCred.port)/1"
|
||||
|
||||
Write-Output "=== MinIO bucket $Bucket ==="
|
||||
$minioRoot = @{}
|
||||
Get-Content "C:\yutongda\config\minio.env" | ForEach-Object {
|
||||
if ($_ -match '^(MINIO_ROOT_USER|MINIO_ROOT_PASSWORD)=(.*)$') { $minioRoot[$matches[1]] = $matches[2] }
|
||||
}
|
||||
$minioApp = @{}
|
||||
Get-Content "C:\yutongda\config\minio-app.env" | ForEach-Object {
|
||||
if ($_ -match '^(OBJECT_STORAGE_ACCESS_KEY|OBJECT_STORAGE_SECRET_KEY)=(.*)$') { $minioApp[$matches[1]] = $matches[2] }
|
||||
}
|
||||
$mc = "C:\yutongda\downloads\mc.exe"
|
||||
& $mc alias set localminio http://127.0.0.1:9000 $minioRoot["MINIO_ROOT_USER"] $minioRoot["MINIO_ROOT_PASSWORD"] --api S3v4 | Out-Null
|
||||
$mb = & $mc mb "localminio/$Bucket" --ignore-existing 2>&1
|
||||
Write-Output ("mb=" + ($mb | ForEach-Object { "$_" }))
|
||||
$policyPath = Join-Path $SqlDir "minio-inquiry-robot-policy.json"
|
||||
@"
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:*"],
|
||||
"Resource": ["arn:aws:s3:::$Bucket", "arn:aws:s3:::$Bucket/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
"@ | Set-Content $policyPath -Encoding ASCII
|
||||
& $mc admin policy create localminio inquiry_robot_full $policyPath 2>&1 | ForEach-Object { "policy_create=$_" }
|
||||
& $mc admin policy attach localminio inquiry_robot_full --user $minioApp["OBJECT_STORAGE_ACCESS_KEY"] 2>&1 | ForEach-Object { "policy_attach=$_" }
|
||||
& $mc alias set inquiryapp http://127.0.0.1:9000 $minioApp["OBJECT_STORAGE_ACCESS_KEY"] $minioApp["OBJECT_STORAGE_SECRET_KEY"] --api S3v4 | Out-Null
|
||||
$smokeLocal = Join-Path $env:TEMP "inquiry_robot_smoke.txt"
|
||||
Set-Content $smokeLocal -Value ("smoke " + (Get-Date).ToString("o")) -Encoding ASCII
|
||||
$cp = & $mc cp $smokeLocal "inquiryapp/$Bucket/provision/smoke.txt" 2>&1
|
||||
Write-Output ("cp=" + ($cp | ForEach-Object { "$_" }))
|
||||
$ls = & $mc ls "inquiryapp/$Bucket/provision/" 2>&1
|
||||
Write-Output ("ls=" + ($ls | ForEach-Object { "$_" }))
|
||||
if (($cp | Out-String) -match 'ERROR' -or ($ls | Out-String) -match 'ERROR') {
|
||||
# fallback: put with root alias
|
||||
Write-Output "APP_PUT_FAIL_TRY_ROOT"
|
||||
& $mc cp $smokeLocal "localminio/$Bucket/provision/smoke.txt" 2>&1 | ForEach-Object { "root_cp=$_" }
|
||||
& $mc ls "localminio/$Bucket/provision/" 2>&1 | ForEach-Object { "root_ls=$_" }
|
||||
}
|
||||
Write-Output "MINIO_OK"
|
||||
|
||||
Write-Output "=== MySQL/PG SQL ==="
|
||||
$mysqlPass = New-Secret 40
|
||||
$pgPass = New-Secret 40
|
||||
@"
|
||||
CREATE DATABASE IF NOT EXISTS ``inquiry_robot`` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE USER IF NOT EXISTS 'inquiry_robot'@'10.206.0.15' IDENTIFIED BY '$mysqlPass';
|
||||
CREATE USER IF NOT EXISTS 'inquiry_robot'@'%' IDENTIFIED BY '$mysqlPass';
|
||||
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'10.206.0.15';
|
||||
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
"@ | Set-Content (Join-Path $SqlDir "01_create_inquiry_robot_mysql.sql") -Encoding UTF8
|
||||
|
||||
@"
|
||||
CREATE USER inquiry_robot_runtime WITH PASSWORD '$pgPass';
|
||||
CREATE DATABASE inquiry_robot_runtime OWNER inquiry_robot_runtime ENCODING 'UTF8' TEMPLATE template0;
|
||||
GRANT ALL PRIVILEGES ON DATABASE inquiry_robot_runtime TO inquiry_robot_runtime;
|
||||
"@ | Set-Content (Join-Path $SqlDir "02_create_inquiry_robot_pg.sql") -Encoding UTF8
|
||||
|
||||
@{
|
||||
mysql_user = "inquiry_robot"
|
||||
mysql_password = $mysqlPass
|
||||
pg_user = "inquiry_robot_runtime"
|
||||
pg_password = $pgPass
|
||||
createdAt = (Get-Date).ToString("o")
|
||||
} | ConvertTo-Json | Set-Content (Join-Path $Ops "inquiry_robot_db_secrets.json") -Encoding UTF8
|
||||
|
||||
# Try admin-secrets.env if exists
|
||||
$adminEnv = Join-Path $Ops "admin-secrets.env"
|
||||
$mysqlCreated = $false
|
||||
$pgCreated = $false
|
||||
if (Test-Path $adminEnv) {
|
||||
$admin = @{}
|
||||
Get-Content $adminEnv | ForEach-Object {
|
||||
if ($_ -match '^(MYSQL_ADMIN_USER|MYSQL_ADMIN_PASSWORD|PG_ADMIN_USER|PG_ADMIN_PASSWORD)=(.*)$') { $admin[$matches[1]] = $matches[2] }
|
||||
}
|
||||
if ($admin.MYSQL_ADMIN_USER -and $admin.MYSQL_ADMIN_PASSWORD) {
|
||||
$mysqlExe = "C:\yutongda\tools\mysql-8.0.39-winx64\bin\mysql.exe"
|
||||
Get-Content (Join-Path $SqlDir "01_create_inquiry_robot_mysql.sql") -Raw |
|
||||
& $mysqlExe -h 10.206.0.14 -P 3306 -u $admin.MYSQL_ADMIN_USER "-p$($admin.MYSQL_ADMIN_PASSWORD)" --connect-timeout=15 2>&1 |
|
||||
ForEach-Object { if ($_ -notmatch 'Using a password') { "mysql=$_" } }
|
||||
if ($LASTEXITCODE -eq 0) { $mysqlCreated = $true }
|
||||
}
|
||||
if ($admin.PG_ADMIN_USER -and $admin.PG_ADMIN_PASSWORD) {
|
||||
$env:PGPASSWORD = $admin.PG_ADMIN_PASSWORD
|
||||
$psql = "C:\yutongda\tools\pgsql\bin\psql.exe"
|
||||
& $psql -h 10.206.0.14 -p 5432 -U $admin.PG_ADMIN_USER -d postgres -v ON_ERROR_STOP=1 -c "SELECT 1" 2>&1 | ForEach-Object { "pgprobe=$_" }
|
||||
# create user/db with separate commands (more reliable than multi-statement file)
|
||||
& $psql -h 10.206.0.14 -p 5432 -U $admin.PG_ADMIN_USER -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'; END IF; END `$`$;" 2>&1 | ForEach-Object { "pguser=$_" }
|
||||
& $psql -h 10.206.0.14 -p 5432 -U $admin.PG_ADMIN_USER -d postgres -v ON_ERROR_STOP=1 -c "SELECT 'exists' FROM pg_database WHERE datname='inquiry_robot_runtime'" 2>&1 | ForEach-Object { "pgdbcheck=$_" }
|
||||
$existsDb = & $psql -h 10.206.0.14 -p 5432 -U $admin.PG_ADMIN_USER -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='inquiry_robot_runtime'" 2>$null
|
||||
if (-not $existsDb) {
|
||||
& $psql -h 10.206.0.14 -p 5432 -U $admin.PG_ADMIN_USER -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE inquiry_robot_runtime OWNER inquiry_robot_runtime ENCODING 'UTF8' TEMPLATE template0;" 2>&1 | ForEach-Object { "pgdb=$_" }
|
||||
}
|
||||
$pgCreated = $true
|
||||
}
|
||||
} else {
|
||||
Write-Output "NEED_DBA_FOR_MYSQL_PG"
|
||||
}
|
||||
|
||||
Write-Output "=== patch .env ==="
|
||||
$envPath = Join-Path $Root ".env"
|
||||
if (-not (Test-Path $envPath)) {
|
||||
"YTD_ENV=test`r`nYTD_DEPLOY_ROOT=E:\wwwroot`r`nYTD_CUTOVER_TARGET=replace-yutongda`r`n" | Set-Content $envPath -Encoding UTF8
|
||||
}
|
||||
$pairs = @{
|
||||
MYSQL_HOST = "10.206.0.14"
|
||||
MYSQL_PORT = "3306"
|
||||
MYSQL_DB = "inquiry_robot"
|
||||
MYSQL_USER = "inquiry_robot"
|
||||
MYSQL_PASSWORD = $mysqlPass
|
||||
YTD_MYSQL_URL = "jdbc:mysql://10.206.0.14:3306/inquiry_robot?characterEncoding=UTF-8&useUnicode=true&useSSL=true&requireSSL=true&verifyServerCertificate=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai"
|
||||
PG_HOST = "10.206.0.14"
|
||||
PG_PORT = "5432"
|
||||
PG_DATABASE = "inquiry_robot_runtime"
|
||||
PG_USER = "inquiry_robot_runtime"
|
||||
PG_PASSWORD = $pgPass
|
||||
PG_SSLMODE = "prefer"
|
||||
YTD_REDIS_HOST = $redisCred.host
|
||||
YTD_REDIS_PORT = "$($redisCred.port)"
|
||||
YTD_REDIS_USERNAME = $redisCred.application_username
|
||||
REDIS_URL = $redisUrl
|
||||
REDIS_KEY_PREFIX = "inquiry_robot:"
|
||||
REDIS_REQUIRED = "true"
|
||||
OBJECT_STORAGE_ENDPOINT_URL = "http://127.0.0.1:9000"
|
||||
OBJECT_STORAGE_BUCKET = $Bucket
|
||||
OBJECT_STORAGE_ACCESS_KEY = $minioApp["OBJECT_STORAGE_ACCESS_KEY"]
|
||||
OBJECT_STORAGE_SECRET_KEY = $minioApp["OBJECT_STORAGE_SECRET_KEY"]
|
||||
OBJECT_STORAGE_PATH_STYLE = "true"
|
||||
OBJECT_STORAGE_REGION = "us-east-1"
|
||||
}
|
||||
Upsert-Env $envPath $pairs
|
||||
if (Test-Path "E:\wwwroot\agent\current") {
|
||||
Copy-Item $envPath "E:\wwwroot\agent\current\.env" -Force
|
||||
Write-Output "AGENT_ENV_SYNCED"
|
||||
}
|
||||
|
||||
# verify env keys present (no values)
|
||||
Select-String -Path $envPath -Pattern '^(MYSQL_DB|PG_DATABASE|REDIS_KEY_PREFIX|OBJECT_STORAGE_BUCKET)=' | ForEach-Object { $_.Line.Trim() }
|
||||
|
||||
@{
|
||||
redis = $true
|
||||
minioBucket = $Bucket
|
||||
mysqlCreated = $mysqlCreated
|
||||
pgCreated = $pgCreated
|
||||
needDba = (-not $mysqlCreated -or -not $pgCreated)
|
||||
sqlDir = $SqlDir
|
||||
updatedAt = (Get-Date).ToString("o")
|
||||
} | ConvertTo-Json | Tee-Object -FilePath (Join-Path $Ops "data-plane-status.json")
|
||||
Write-Output "PROVISION_DONE"
|
||||
Reference in New Issue
Block a user