Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"agent-api",
"agent-client",
"agent-types",
"agent-types/versions",
"crucible-client-types",
"common",
"control-client",
Expand Down Expand Up @@ -147,6 +148,7 @@ crucible = { path = "./upstairs" }
crucible-agent-api = { path = "./agent-api" }
crucible-agent-client = { path = "./agent-client" }
crucible-agent-types = { path = "./agent-types" }
crucible-agent-types-versions = { path = "./agent-types/versions" }
crucible-client-types = { path = "./crucible-client-types" }
crucible-common = { path = "./common" }
crucible-control-client = { path = "./control-client" }
Expand Down
4 changes: 1 addition & 3 deletions agent-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ license = "MPL-2.0"
edition = "2024"

[dependencies]
crucible-agent-types.workspace = true
crucible-agent-types-versions.workspace = true
crucible-workspace-hack.workspace = true
dropshot.workspace = true
dropshot-api-manager-types.workspace = true
schemars.workspace = true
serde.workspace = true
68 changes: 16 additions & 52 deletions agent-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use std::collections::BTreeMap;

use crucible_agent_types::{
region::{CreateRegion, Region, RegionId},
snapshot::{RunningSnapshot, Snapshot},
};
use crucible_agent_types_versions::latest;
use dropshot::{
HttpError, HttpResponseDeleted, HttpResponseOk, Path, RequestContext,
TypedBody,
};
use dropshot_api_manager_types::api_versions;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

api_versions!([
// WHEN CHANGING THE API (part 1 of 2):
Expand Down Expand Up @@ -51,33 +44,33 @@ pub trait CrucibleAgentApi {
}]
async fn region_list(
rqctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<Vec<Region>>, HttpError>;
) -> Result<HttpResponseOk<Vec<latest::region::Region>>, HttpError>;

#[endpoint {
method = POST,
path = "/crucible/0/regions",
}]
async fn region_create(
rqctx: RequestContext<Self::Context>,
body: TypedBody<CreateRegion>,
) -> Result<HttpResponseOk<Region>, HttpError>;
body: TypedBody<latest::region::CreateRegion>,
) -> Result<HttpResponseOk<latest::region::Region>, HttpError>;

#[endpoint {
method = GET,
path = "/crucible/0/regions/{id}",
}]
async fn region_get(
rqctx: RequestContext<Self::Context>,
path: Path<RegionPath>,
) -> Result<HttpResponseOk<Region>, HttpError>;
path: Path<latest::region::RegionPath>,
) -> Result<HttpResponseOk<latest::region::Region>, HttpError>;

#[endpoint {
method = DELETE,
path = "/crucible/0/regions/{id}",
}]
async fn region_delete(
rqctx: RequestContext<Self::Context>,
path: Path<RegionPath>,
path: Path<latest::region::RegionPath>,
) -> Result<HttpResponseDeleted, HttpError>;

#[endpoint {
Expand All @@ -86,25 +79,25 @@ pub trait CrucibleAgentApi {
}]
async fn region_get_snapshots(
rqctx: RequestContext<Self::Context>,
path: Path<RegionPath>,
) -> Result<HttpResponseOk<GetSnapshotResponse>, HttpError>;
path: Path<latest::region::RegionPath>,
) -> Result<HttpResponseOk<latest::snapshot::GetSnapshotResponse>, HttpError>;

#[endpoint {
method = GET,
path = "/crucible/0/regions/{id}/snapshots/{name}",
}]
async fn region_get_snapshot(
rqctx: RequestContext<Self::Context>,
path: Path<GetSnapshotPath>,
) -> Result<HttpResponseOk<Snapshot>, HttpError>;
path: Path<latest::snapshot::GetSnapshotPath>,
) -> Result<HttpResponseOk<latest::snapshot::Snapshot>, HttpError>;

#[endpoint {
method = DELETE,
path = "/crucible/0/regions/{id}/snapshots/{name}",
}]
async fn region_delete_snapshot(
rqctx: RequestContext<Self::Context>,
path: Path<DeleteSnapshotPath>,
path: Path<latest::snapshot::DeleteSnapshotPath>,
) -> Result<HttpResponseDeleted, HttpError>;

#[endpoint {
Expand All @@ -113,44 +106,15 @@ pub trait CrucibleAgentApi {
}]
async fn region_run_snapshot(
rqctx: RequestContext<Self::Context>,
path: Path<RunSnapshotPath>,
) -> Result<HttpResponseOk<RunningSnapshot>, HttpError>;
path: Path<latest::snapshot::RunSnapshotPath>,
) -> Result<HttpResponseOk<latest::snapshot::RunningSnapshot>, HttpError>;

#[endpoint {
method = DELETE,
path = "/crucible/0/regions/{id}/snapshots/{name}/run",
}]
async fn region_delete_running_snapshot(
rc: RequestContext<Self::Context>,
path: Path<RunSnapshotPath>,
path: Path<latest::snapshot::RunSnapshotPath>,
) -> Result<HttpResponseDeleted, HttpError>;
}

#[derive(Deserialize, JsonSchema)]
pub struct RegionPath {
pub id: RegionId,
}

#[derive(Serialize, JsonSchema)]
pub struct GetSnapshotResponse {
pub snapshots: Vec<Snapshot>,
pub running_snapshots: BTreeMap<String, RunningSnapshot>,
}

#[derive(Deserialize, JsonSchema)]
pub struct GetSnapshotPath {
pub id: RegionId,
pub name: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct DeleteSnapshotPath {
pub id: RegionId,
pub name: String,
}

#[derive(Deserialize, JsonSchema)]
pub struct RunSnapshotPath {
pub id: RegionId,
pub name: String,
}
4 changes: 2 additions & 2 deletions agent-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ license = "MPL-2.0"
edition = "2024"

[dependencies]
chrono.workspace = true
crucible-agent-types-versions.workspace = true
crucible-smf.workspace = true
crucible-workspace-hack.workspace = true
serde.workspace = true
schemars.workspace = true
serde.workspace = true

[dev-dependencies]
serde_json.workspace = true
2 changes: 1 addition & 1 deletion agent-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

pub mod region;
pub mod smf;
Expand Down
93 changes: 2 additions & 91 deletions agent-types/src/region.rs
Original file line number Diff line number Diff line change
@@ -1,95 +1,6 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use std::net::SocketAddr;

use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum State {
Requested,
Created,
Tombstoned,
Destroyed,
Failed,
}

// If not provided, select None as the default for source.
fn source_default() -> Option<SocketAddr> {
None
}

// If not provided, select false as the default for read only.
fn read_only_default() -> bool {
false
}

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
pub struct Region {
pub id: RegionId,
pub state: State,

// Creation parameters
pub block_size: u64,
pub extent_size: u64,
pub extent_count: u32,
pub encrypted: bool,

// Run-time parameters
pub port_number: u16,
pub cert_pem: Option<String>,

// TODO should skip serializing this on list regions response, but this
// causes crucible.json to not have it
// #[serde(skip_serializing)]
pub key_pem: Option<String>,

pub root_pem: Option<String>,
// If this region was created as part of a clone.
#[serde(default = "source_default")]
pub source: Option<SocketAddr>,

// If this region is read only
#[serde(default = "read_only_default")]
pub read_only: bool,
}

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
pub struct CreateRegion {
pub id: RegionId,

pub block_size: u64,
pub extent_size: u64,
pub extent_count: u32,
pub encrypted: bool,

pub cert_pem: Option<String>,
pub key_pem: Option<String>,
pub root_pem: Option<String>,
// TODO base64 encoded der too?
/// If requested, copy the extent contents from the provided IP:Port
///
/// Regions created from a source will be started read_only
pub source: Option<SocketAddr>,
}

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(
Serialize,
Deserialize,
JsonSchema,
Debug,
PartialEq,
Eq,
Clone,
PartialOrd,
Ord,
)]
pub struct RegionId(pub String);
pub use crucible_agent_types_versions::latest::region::*;

#[cfg(test)]
mod test {
Expand Down
2 changes: 1 addition & 1 deletion agent-types/src/smf.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

use crucible_smf::scf_type_t;

Expand Down
23 changes: 4 additions & 19 deletions agent-types/src/snapshot.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
// Copyright 2025 Oxide Computer Company
// Copyright 2026 Oxide Computer Company

pub use crucible_agent_types_versions::latest::snapshot::*;

use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::region::{RegionId, State};

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
pub struct Snapshot {
pub name: String,
pub created: DateTime<Utc>,
}

#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq, Clone)]
pub struct RunningSnapshot {
pub id: RegionId,
pub name: String,
pub port_number: u16,
pub state: State,
}
use crate::region::RegionId;

pub struct CreateRunningSnapshotRequest {
pub id: RegionId,
Expand Down
11 changes: 11 additions & 0 deletions agent-types/versions/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "crucible-agent-types-versions"
version = "0.1.0"
license = "MPL-2.0"
edition = "2024"

[dependencies]
chrono.workspace = true
crucible-workspace-hack.workspace = true
schemars.workspace = true
serde.workspace = true
6 changes: 6 additions & 0 deletions agent-types/versions/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2026 Oxide Computer Company

//! Functional code for the latest versions of types.

// Currently a placeholder. Remove this comment when functional code is added in
// a submodule.
6 changes: 6 additions & 0 deletions agent-types/versions/src/initial/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2026 Oxide Computer Company

//! Version `INITIAL` of the Crucible Agent API.

pub mod region;
pub mod snapshot;
Loading