Thank you so much for having interesting in contributing to the project.
-
crashes, panics and such should be reported there directly. Code should not crash, it is a bug.
-
missing or wrong arguments, errors with response, etc are most likely caused by wrong OpenAPI schemas. please report here, but do not start working on addressing those since they need to be fixed either in codegenerator or in the service itself.
-
missing commands in the CLI are most likely not enabled yet (generated by the codegenerator, but not included/imported yet as modules). Please report an issue or propose PR including generated modules in the source code.
Most parts of the code are automatically generated by https://opendev.org/openstack/codegenerator and therefore direct changes to the generated code are not making sense. Instead the codegenerator should be adapted where necessary. This approach forces code to be consistent.
All generated modules have a corresponding notice in the header.
if you have an idea how generated code can be improved open an issue or discussion.
Authentication plugins use a two-layer approach to ensure they are loaded at runtime:
Each auth plugin crate (e.g., openstack-sdk-auth-password) registers itself at
compile time using the inventory crate:
static PLUGIN: PasswordAuthenticator = PasswordAuthenticator;
inventory::submit! {
openstack_sdk_auth_core::AuthPluginRegistration { method: &PLUGIN }
}The SDK iterates inventory::iter::<AuthPluginRegistration> at runtime to
discover available authenticators. The inventory crate uses linker sections to
collect registrations across crates, which means the plugin crate must be linked
for its registration to appear.
Without explicit references, the Rust linker may strip unused plugin crates. The
openstack_sdk crate uses a build.rs script to automatically generate
plugin_anchors.rs with #[cfg]-gated imports that reference each plugin's
#[used] ANCHOR static. This ensures the linker includes all enabled plugins.
Key points:
- Non-optional plugins are always anchored (e.g.,
password,token,application_credential). - Optional plugins are feature-gated (e.g.,
keystone_ngenables JWT and federation,passkeyenables WebAuthn). - Adding a new plugin requires adding it as a dependency in
openstack_sdk/Cargo.toml. Thebuild.rswill automatically anchor it (with appropriate#[cfg]if optional).
- Create the plugin crate under
sdk/auth-<name>/. - Implement
OpenStackAuthTypeand submitAuthPluginRegistrationviainventory::submit!. - Optionally implement
OpenStackMultifactorAuthMethodfor multifactor support. - Add a
#[used] ANCHORstatic to prevent linker stripping. - Add the crate as a dependency in
openstack_sdk/Cargo.toml. - Add a feature flag if the plugin is optional.
-
If a function needs to take ownership of the data, pass by value
-
If a function only needs to read the data, pass a reference (borrow)
-
If a function needs to change the data, pass a mutable reference.
-
pre-commit is present in the repository to help ensuring linters will not complain later. just issue
pre-commit installin the repository root to enable it. -
spell checking is performed using 'crate-ci/typos' and is a mandatory check.
-
doctstrings in generated files are produced from OpenStack services code. There is no point fixing them here and instead syntax or typos should be fixed upstream. The only exception is that during code generation spelling issues are automatically addressed by
typos -w. -
Merge commits are forbidden. Whenever you open a PR please update it with rebase and not a merge commit. It is also recommended to "allow edits from maintainers" to help us get the quick fixes to the PR.
-
PRs are merged as squash commits.
There are 2 projects being used to take care of release process:
-
release-plzvalidates challenges and prepares PR to cut a release proposing the corresponding version. Merging PR will triggerrelease-plzto create new version, tag it, perform Rust release to <crates.io>. -
cargo distbuilds and uploads binary artifacts to the GH releases. This is triggered by creating a git tagCRATE_NAME_vMAJ.MIN.PATCH. Part of the normal PR CIcargo distis also building artifacts and stores them as CI artifacts.
Since every crate in the workspace is currently having independent versioning it is not trivial to rely on "latest" release. This is explicitly harming publishing binary artifacts. As of now every crate is released in a separate tag with binary artifacts included in the corresponding release. Maybe combined tag (i.e. in a form YYYY-MM-DD) may be produced repackaging binaries, but it is not the case right now.
The repository is a Rust workspace that bundles:
| Category | Crates (paths) |
|---|---|
| CLI entry points | cli/* (e.g. cli/compute, cli/network …) |
| SDK core | openstack_sdk |
| SDK sub‑modules | sdk/* (auth, compute, identity, …) |
| Types | openstack_types, types/* |
| TUI (terminal UI) | openstack_tui |
| Misc utilities | xtask, fuzz |
The workspace definition lives in Cargo.toml (members / default‑members).
Agents can discover all crates by grepping members = in that file.
| Goal | Command (run from repository root) |
|---|---|
| Build every binary (release) | cargo build --workspace --release |
| Run all unit + integration tests | cargo test --workspace --all-features |
| Run only the TUI tests | cargo test -p openstack_tui |
| Lint & format (pre‑commit) | pre-commit run --all-files |
| Check code generation consistency | cargo run -p codegenerator -- --check |
| Generate documentation | cargo doc --workspace --no-deps |
- Most SDK/Types/Cli crates are generated by
https://opendev.org/openstack/codegenerator. Generated files contain a
header comment
// AUTO‑GENERATED– those files should be never edited directly. - To modify generated behavior, edit the code‑generator templates or the service OpenAPI specs and then re‑run:
cargo run -p codegenerator -- generate- After regeneration, run the lint step above to ensure the workspace stays clean.
Each auth plugin crate (e.g. sdk/auth-password) registers a static via:
inventory::submit! {
openstack_sdk_auth_core::AuthPluginRegistration { method: &PLUGIN }
}The SDK iterates inventory::iter::<AuthPluginRegistration> at runtime.
openstack_sdk/build.rs creates plugin_anchors.rs that imports every
plugin’s #[used] ANCHOR static behind feature gates.
What agents should look for:
| Item | Location |
|---|---|
| Plugin list generation | openstack_sdk/build.rs |
| Anchor definitions | #[used] static ANCHOR: u8 = 0; in each auth crate |
| Feature‑gate mapping | Cargo.toml feature sections for optional plugins (keystone_ng, passkey, …) |
- Create
sdk/auth-<name>/Cargo.tomland add a#[used] ANCHORstatic. - Implement
OpenStackAuthTypeand submit registration. - Add the crate as a dependency in
openstack_sdk/Cargo.toml. - (Optional) Add a feature flag in
openstack_sdk/Cargo.toml. - Run
cargo build; thebuild.rswill automatically anchor it.
Agents can verify step 3 by grepping the workspace Cargo.toml for the new
crate name.
/ – workspace root
├─ Cargo.toml – workspace definition
├─ openstack_cli/ – CLI entry point
├─ openstack_sdk/ – SDK entry point (runtime glue)
├─ openstack_tui/ – terminal UI binary
├─ openstack_types/ – REST response type definitions
├─ cli/ – individual service CLIs (e.g. `cli/compute`)
├─ sdk/auth_* – Authentication plugins for SDK
├─ sdk/ – generated service binding crates (compute, identity, …)
├─ types/ – shared type definitions per service
├─ xtask/ – custom cargo tasks (build scripts)
├─ doc/ – MkDocs source for documentation
└─ .github/… – CI / release scripts
- DCO sign‑off: use
git commit -sto automatically add aSigned-off-by:line with the configured user name and email, satisfying the Developer Certificate of Origin requirement. - Pre‑commit checks: run
pre-commit run --all-filesbefore pushing. - Committed verification: ensure the repository passes the
committedchecks defined incommitted.toml(runcommitted). - Commit message format (conventional commits):
- Conventional commit type in the subject line
- Subject line capitalized and ≤ 50 characters.
- Body lines wrapped at ≤ 72 characters.
- Separate subject and body with a blank line.
- End with a
Signed-off-by:trailer.
<!--
AI_AGENT_METADATA
{
"workspace_root": "openstack",
"cargo_toml": "Cargo.toml",
"generated_crates_path": "sdk/",
"auth_plugin_crate_prefix": "sdk/auth-",
"tui_entry": "openstack_tui",
"cli_entry_prefix": "cli/",
"cli_root": "openstack_cli",
"types_root": "openstack_types"
}
-->The JSON can be read by automation tools to locate key paths without fragile string matching.