Skip to content

Commit 43cb693

Browse files
committed
mk-oracle, mk-sql: stop leaving temp directories behind on Windows
Three test helpers each left one directory in %TEMP% per run on the Windows CI nodes. permissions-check-run.ps1 restricts the ACL of the unpacked Oracle client runtime to Administrators and SYSTEM, and never restored it. The cleanup in the finally block runs unelevated and could therefore no longer delete oci.dll. The elevated script now hands the rights back once its checks are done. The finally block grants them back as well, for the case where the elevated script ended early, and reports a directory that still cannot be removed instead of discarding the error. make_endpoint_tns_admin_dir created its TNS_ADMIN directory with create_dir_all and returned a plain path, so nothing ever deleted it. It now returns a TempDir, which the calling test holds until it ends. LogMe wrote its log file into a TempDir. The process-global logger keeps that file open until the test process exits, Windows refuses to delete an open file, and TempDir discards the resulting error. The log now goes to one fixed directory that each run clears when it starts. Change-Id: Ic985f0dd0457f6dc0eb1c6afa498899ccdd1decc
1 parent 0761dd3 commit 43cb693

4 files changed

Lines changed: 45 additions & 22 deletions

File tree

packages/mk-oracle/permissions-check-run.ps1

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ while (!(Test-Path "$root_dir/.werks" -ErrorAction SilentlyContinue)) {
4444
Write-Host "Building $package_name..." -ForegroundColor White
4545
Push-Location $PSScriptRoot
4646
$temp_dir = Join-Path $env:TEMP "mk-oracle-perms-check-$([System.IO.Path]::GetRandomFileName())"
47+
$runtime_path = "$temp_dir/runtimes/plugins/packages/mk-oracle/runtime"
48+
$current_user_sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
4749
New-Item -ItemType Directory -Path $temp_dir -Force | Out-Null
4850
try {
4951
& cargo build --release --package $package_name --target $cargo_target
@@ -61,7 +63,6 @@ try {
6163
if ($LASTEXITCODE -ne 0) { Write-Error "OCI download failed" }
6264

6365
$oci_zip = & bazel cquery $target --output=starlark --starlark:expr='target.files.to_list()[0].path'
64-
$runtime_path = "$temp_dir/runtimes/plugins/packages/mk-oracle/runtime"
6566
New-Item -ItemType Directory -Path $runtime_path -Force | Out-Null
6667
Expand-Archive -Path "$root_dir/$oci_zip" -DestinationPath $runtime_path -Force
6768

@@ -111,9 +112,9 @@ try {
111112
# restrict it to Administrators-only (elevated, so the ACL reset itself
112113
# isn't fighting a UAC-filtered token), then verify it's trusted again.
113114
Write-Host "Step 4: running elevated checks..." -ForegroundColor White
114-
$admin_out_before = "$env:TEMP\perms-check-stdout-before.txt"
115-
$admin_out_after = "$env:TEMP\perms-check-stdout-after.txt"
116-
$admin_sql_out_before = "$env:TEMP\perms-check-sql-stdout-before.txt"
115+
$admin_out_before = Join-Path $temp_dir "perms-check-stdout-before.txt"
116+
$admin_out_after = Join-Path $temp_dir "perms-check-stdout-after.txt"
117+
$admin_sql_out_before = Join-Path $temp_dir "perms-check-sql-stdout-before.txt"
117118
$admin_script = Join-Path $temp_dir "admin-check.ps1"
118119
@"
119120
`$ErrorActionPreference = 'Stop'
@@ -124,6 +125,8 @@ Set-Location '$PSScriptRoot'
124125
icacls '$runtime_path' /inheritance:r /remove:g '*S-1-5-32-545' /grant:r '*S-1-5-32-544:(OI)(CI)F' '*S-1-5-18:(OI)(CI)F' /T /C | Out-Null
125126
if (`$LASTEXITCODE -ne 0) { exit 2 }
126127
& '$binary' -c tests/files/test-mini-one-section.yml *> '$admin_out_after'
128+
# Hand the directory back to the account that created it
129+
icacls '$runtime_path' /grant '*${current_user_sid}:(OI)(CI)F' /T /C | Out-Null
127130
"@ | Set-Content -Path $admin_script -Encoding utf8
128131
$proc = Start-Process pwsh -ArgumentList "-NoProfile -File `"$admin_script`"" -Verb RunAs -Wait -PassThru -WindowStyle Hidden
129132
if ($proc.ExitCode -ne 0) {
@@ -143,23 +146,20 @@ if (`$LASTEXITCODE -ne 0) { exit 2 }
143146
$refusal = "No Oracle client runtime found"
144147

145148
$output_before = Get-Content $admin_out_before -Raw
146-
Remove-Item $admin_out_before -ErrorAction SilentlyContinue
147149
if ($output_before -match '<<<' -or $output_before -notmatch $refusal) {
148150
Write-Host $output_before -ForegroundColor Red
149151
Write-Error "FAIL: expected '$refusal' and no section output from admin run before restricting permissions"
150152
}
151153
Write-Host "OK: root can't exec non-root code" -ForegroundColor Green
152154

153155
$sql_output_before = Get-Content $admin_sql_out_before -Raw
154-
Remove-Item $admin_sql_out_before -ErrorAction SilentlyContinue
155156
if ($sql_output_before -match '<<<' -or $sql_output_before -notmatch $refusal) {
156157
Write-Host $sql_output_before -ForegroundColor Red
157158
Write-Error "FAIL: expected '$refusal' and no section output from admin run with custom SQL file"
158159
}
159160
Write-Host "OK: root can't read non-root custom SQL file" -ForegroundColor Green
160161

161162
$output_after = Get-Content $admin_out_after -Raw
162-
Remove-Item $admin_out_after -ErrorAction SilentlyContinue
163163
# Same shape as the non-elevated run (step 3): real section output, not
164164
# just any bytes — error text on stderr must not count as success.
165165
$after_lines = ($output_after -split "`n" | Where-Object { $_.Trim() -ne "" })
@@ -176,6 +176,14 @@ if (`$LASTEXITCODE -ne 0) { exit 2 }
176176

177177
}
178178
finally {
179-
Remove-Item $temp_dir -Recurse -Force -ErrorAction SilentlyContinue
179+
if (Test-Path $runtime_path) {
180+
& icacls $runtime_path /grant "*${current_user_sid}:(OI)(CI)F" /T /C 2>&1 | Out-Null
181+
}
182+
try {
183+
Remove-Item $temp_dir -Recurse -Force
184+
}
185+
catch {
186+
Write-Warning "Leftover directory $temp_dir could not be removed: $_"
187+
}
180188
Pop-Location
181189
}

packages/mk-oracle/tests/common/tools.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use mk_oracle::config::authentication::{AuthType, Role, SqlDbEndpoint};
2121
use mk_oracle::config::ora_sql::Config;
2222
use mk_oracle::types::{Credentials, InstanceAlias};
23+
use tempfile::TempDir;
2324

2425
/// Mandatory reference endpoint for all DB-dependent tests.
2526
pub const ORA_ENDPOINT_ENV_VAR: &str = "CI_ORA2_DB_TEST";
@@ -221,14 +222,15 @@ pub fn make_mini_config_custom_instance(
221222
)
222223
}
223224

224-
/// Writes a tnsnames.ora resolving `alias` to `endpoint` into a
225-
/// process-private directory and returns that directory, suitable as
226-
/// tns_admin. Keeps alias-based tests independent of which reference DB
227-
/// the endpoint env vars point at.
228-
pub fn make_endpoint_tns_admin_dir(endpoint: &SqlDbEndpoint, alias: &str) -> std::path::PathBuf {
229-
let dir =
230-
std::env::temp_dir().join(format!("mk-oracle-test-tns-{}-{alias}", std::process::id()));
231-
std::fs::create_dir_all(&dir).expect("failed to create TNS_ADMIN dir");
225+
/// Writes a tnsnames.ora resolving `alias` to `endpoint` into a temporary
226+
/// directory and returns that directory, suitable as tns_admin. Keeps
227+
/// alias-based tests independent of which reference DB the endpoint env vars
228+
/// point at.
229+
pub fn make_endpoint_tns_admin_dir(endpoint: &SqlDbEndpoint, alias: &str) -> TempDir {
230+
let dir = tempfile::Builder::new()
231+
.prefix(&format!("mk-oracle-test-tns-{alias}-"))
232+
.tempdir()
233+
.expect("failed to create TNS_ADMIN dir");
232234
let content = format!(
233235
r"{alias} =
234236
(DESCRIPTION =
@@ -248,7 +250,7 @@ pub fn make_endpoint_tns_admin_dir(endpoint: &SqlDbEndpoint, alias: &str) -> std
248250
.as_deref()
249251
.expect("endpoint must provide a SID"),
250252
);
251-
std::fs::write(dir.join("tnsnames.ora"), content).expect("failed to write tnsnames.ora");
253+
std::fs::write(dir.path().join("tnsnames.ora"), content).expect("failed to write tnsnames.ora");
252254
dir
253255
}
254256

packages/mk-oracle/tests/test_ora_with_db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ oracle:
466466
&endpoint,
467467
"FREE",
468468
Some(InstanceAlias::from("ora_remote".to_string())),
469-
&tns_admin,
469+
tns_admin.path(),
470470
);
471471
let env = Env::default();
472472
let r = generate_data(&config, &env).await;

packages/mk-sql/tests/common/tools.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,24 +236,37 @@ pub async fn run_get_version(client: &mut UniClient) -> Option<String> {
236236
}
237237
}
238238

239+
/// Directory holding the log file that [`LogMe`] writes.
240+
///
241+
/// Reused by every run.
242+
/// `LogMe` hands the log file to the process-global logger,
243+
/// which keeps that file open until the test process exits. Windows refuses to
244+
/// delete an open file, so a temporary directory created for one run cannot be removed by
245+
/// that same run.
246+
fn log_dir() -> PathBuf {
247+
std::env::temp_dir().join("mk-sql-test-logs")
248+
}
249+
239250
#[allow(dead_code)]
240251
pub struct LogMe {
241-
temp_dir: TempDir,
252+
dir: PathBuf,
242253
name: String,
243254
}
244255

245256
#[allow(dead_code)]
246257
impl LogMe {
247258
pub fn new(name: &str) -> Self {
248-
let dir = create_temp_process_dir();
259+
let dir = log_dir();
260+
let _ = std::fs::remove_dir_all(&dir);
261+
std::fs::create_dir_all(&dir).expect("failed to create log directory");
249262
Self {
250-
temp_dir: dir,
263+
dir,
251264
name: name.to_string(),
252265
}
253266
}
254267

255268
pub fn dir(&self) -> &Path {
256-
self.temp_dir.path()
269+
&self.dir
257270
}
258271

259272
pub fn start(self, level: log::Level) -> Self {

0 commit comments

Comments
 (0)