This repo is a Rust service that provides an Envoy xDS control plane and manages ACME certificates. Use this guide for quick commands and project conventions.
src/Rust service code.test/Containerized integration tests (Pebble + Envoy + xds server).example-config.yamlExample runtime configuration.compose.yamlPodman Compose stack for integration tests.
cargo buildcargo run -- example-config.yamlNotes:
- The service expects exactly one CLI arg: a config YAML path.
- Logging is configured via
RUST_LOG(defaultenvoy_acme_xds=info).
cargo fmtcargo clippy --all-targets --all-features -- -D warningscargo testRun a single test by name:
cargo test <test_name>Run a single test in a specific module:
cargo test module::submodule::test_nameIf no tests exist, add them in src/... with #[cfg(test)] or create
tests/ integration tests. Keep names descriptive and stable for filtering.
From repo root:
./test/cleanup.sh
./test/run-test.sh --rebuildNotes:
- Always run
./test/cleanup.shbefore integration tests to clear thexds-datavolume (ACME account + issued certificates). - Always pass
--rebuildso the xds-server image includes the latest code. --fullcleanup is not required for routine runs; Pebble CA certificates can be reused.
Useful options:
./test/run-test.sh --keep
./test/run-test.sh --rebuildCleanup:
./test/cleanup.sh
./test/cleanup.sh --fullValidation-only check:
./test/verify-validation.shPrereqs for integration tests:
podmanandpodman composeopensslcurl
- Group imports by source with a blank line between groups:
std::...- external crates (
tokio,tracing,serde, etc.) - local crate (
crate::...,super::...)
- Prefer explicit imports over wildcard, except in narrow internal scopes.
- Use rustfmt defaults (no custom config found).
- Keep lines readable; wrap long method chains similar to existing style.
- Align with current patterns for
tracingfields andtokio::spawnblocks.
- Types:
UpperCamelCase(structs, enums, traits). - Functions and variables:
snake_case. - Modules:
snake_casefilenames; public modules re-exported inmod.rs. - Constants:
SCREAMING_SNAKE_CASEif needed.
- Prefer explicit types at public boundaries; use type aliases like
error::Result<T>consistently. - Use
Arcfor shared state across async tasks (tokio::spawn). - Use
RwLockfor shared, frequently-read state when needed.
- The project uses
thiserrorfor error types (src/error.rs). - Prefer returning
Result<T, Error>and using?for propagation. - Convert external errors via
#[from]on enum variants where appropriate. - Add context by wrapping errors with domain-specific messages, not
unwrap. - Only use
expectfor truly unrecoverable states (e.g., signal setup).
- Use
tracingfor structured logs (info!,error!, etc.). - Prefer structured fields for key values (paths, ports, counts).
- Avoid
println!except in CLI usage errors (seemain.rs).
- Use
tokioprimitives for async IO and synchronization. - Avoid blocking operations on async tasks; use
tokio::fsandtokio::net. - Spawn background tasks with clear ownership of cloned state.
- Ensure background tasks do not create update loops (see xds state updater).
- Config structs use
serdewithDeserializeand defaults. - Keep config fields documented with
///comments. - Use
PathBuffor filesystem paths and keep them in configmeta.
- Envoy resources are represented as
serde_json::Valuein config parsing. - Build and merge listener/cluster definitions via
ConfigMergerto ensure ACME challenge routes are injected correctly.
- Keep module boundaries consistent with current layout:
acme/,config/,envoy/,xds/. - Place small, focused helpers near their domain module.
- Re-export public APIs from
mod.rsfiles.
- Update
src/acme/storage.rsfor serialization. - Update any config loaders and tests accordingly.
- Update
src/config/types.rsand addserdedefaults if needed. - Update
example-config.yamlfor documentation.
- Update
src/xds/services andsrc/envoy/builders. - Ensure
XdsStateversioning and notifications are consistent.
- Use a concise, lowercase, prefixed subject:
feat: ...,fix: ...,add: .... - If more detail is needed, add a blank line and a wrapped body explaining the why and key changes.
- Use short paragraphs or bullet lists for multi-part changes.
- Add
Co-Authored-By: Name <email>trailers when pairing or using assistance.
- Do not modify files in
certificates/during normal development. - Integration tests create and remove container data; use
--keepto inspect. - Prefer non-destructive changes; avoid deleting user data without a prompt.