Skip to content

Commit 2f5cf05

Browse files
authored
[openapi-manager] create parent dir when symlinking (#7839)
When a new API is added, we instruct the person adding the API to run `cargo xtask openapi generate` to generate it for the first time. Unfortunately for versioned APIs, this currently results in a failure. For example: ```console eliza@theseus ~/Code/oxide/omicron $ cargo xtask openapi generate Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.40s Running `target/debug/xtask openapi generate` Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.66s Running `target/debug/openapi-manager generate` Generating OpenAPI documents from API definitions ... Loading local OpenAPI documents from "/home/eliza/Code/oxide/omicron/openapi" ... Loading blessed OpenAPI documents from git revision "origin/main" path "openapi" ------- Updating 15 OpenAPI documents... Unchanged bootstrap-agent (lockstep v0.0.1): Bootstrap Agent API Unchanged clickhouse-admin-keeper (lockstep v0.0.1): ClickHouse Cluster Admin Keeper API Unchanged clickhouse-admin-server (lockstep v0.0.1): ClickHouse Cluster Admin Server API Unchanged clickhouse-admin-single (lockstep v0.0.1): ClickHouse Single-Node Admin Server API Unchanged cockroach-admin (lockstep v0.0.1): CockroachDB Cluster Admin API Unchanged dns-server (versioned v1.0.0 (blessed)): Internal DNS Unchanged dns-server "latest" symlink Stale ereporter (versioned v1.0.0 (added locally)): Ereporter API FIX FAILED fix "write new file ereporter/ereporter-1.0.0-e4bfb2.json from generated\n": failed to write to `/home/eliza/Code/oxide/omicron/openapi/ereporter/ereporter-1.0.0-e4bfb2.json`: No such file or directory (os error 2) at path "/home/eliza/Code/oxide/omicron/openapi/ereporter/.atomicwritedybktN" Stale ereporter "latest" symlink FIX FAILED fix "update symlink to point to ereporter-1.0.0-e4bfb2.json\n": failed to symlink file from ereporter-1.0.0-e4bfb2.json to /home/eliza/Code/oxide/omicron/openapi/ereporter/ereporter-latest.json: No such file or directory (os error 2) Unchanged gateway (lockstep v0.0.1): Oxide Management Gateway Service API Unchanged installinator (lockstep v0.0.1): Installinator API Unchanged nexus (lockstep v20250212.0.0): Oxide Region API Unchanged nexus-internal (lockstep v0.0.1): Nexus internal API Unchanged oximeter (lockstep v0.0.1): Oxide Oximeter API Unchanged repo-depot (lockstep v0.0.1): Oxide TUF Repo Depot API Unchanged sled-agent (lockstep v0.0.1): Oxide Sled Agent API Unchanged wicketd (lockstep v0.0.1): Oxide Technician Port Control Service ------- Failure 15 documents: 0 changes made, 14 unchanged, 2 failed ``` This is because versioned APIs live in their own subdirectories of `openapi/`, and when a new API is added, its subdirectory will not exist. When we try to write the API spec to that location, we can't, because the parent directory doesn't exist. This commit fixes that by changing the OpenAPI manager to attempt to create the parent directory if it isn't present. Hopefully this should prevent others from hitting this snag in the future!
1 parent 903b992 commit 2f5cf05

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

dev-tools/openapi-manager/src/validation.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ pub fn overwrite_file(
126126
return Ok(OverwriteStatus::Unchanged);
127127
}
128128

129+
// Make sure the parent directory exists before trying to write any files.
130+
// N.B. that it's very unlikely that `parent()` would be `None` --- why are
131+
// you putting your OpenAPI document in `/`? --- but we may as well not fail
132+
// if that is the case...
133+
if let Some(parent) = path.parent() {
134+
if !parent.exists() {
135+
fs_err::create_dir_all(path).with_context(|| {
136+
format!("failed to create parent directory for '{}'", path)
137+
})?
138+
}
139+
}
140+
129141
AtomicFile::new(path, atomicwrites::OverwriteBehavior::AllowOverwrite)
130142
.write(|f| f.write_all(contents))
131143
.with_context(|| format!("failed to write to `{}`", path))?;

0 commit comments

Comments
 (0)