Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System Update API #2100

Merged
merged 50 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b7b60c0
stub system update status, list, and detail
david-crespo Dec 29, 2022
9a5ae8c
wrap semver::Version and impl JsonSchema for it
david-crespo Dec 29, 2022
468a263
/components endpoints for update detail and system version, tweak names
david-crespo Dec 29, 2022
1ce8ae6
add update start and stop without deciding what their responses are
david-crespo Dec 29, 2022
9d86f52
move AssetIdentityMetadata next to Asset, add identity() method
david-crespo Dec 30, 2022
24ab40c
add system updates table
david-crespo Dec 30, 2022
cde4429
stub integration tests for stubbed endpoints
david-crespo Jan 2, 2023
859605c
so damn close with the component join table but it doesn't compile
david-crespo Jan 2, 2023
e3e3123
thanks @smklein
david-crespo Jan 2, 2023
4eed1d7
update openapi spec, fix nexus method name
david-crespo Jan 2, 2023
afe32c1
Merge branch 'main' into stub-update-api
david-crespo Jan 2, 2023
186994e
paginate list of updates
david-crespo Jan 3, 2023
ea4bbde
implement to/from sql for semver version
david-crespo Jan 4, 2023
38e3444
Merge branch 'main' into stub-update-api
david-crespo Jan 4, 2023
dea5ada
fix VersionStatus enum in openapi spec with serde tag
david-crespo Jan 4, 2023
a7d898c
use list of component types from RFD 300
david-crespo Jan 4, 2023
54e1f45
updateable components table (TODO: status and reason)
david-crespo Jan 4, 2023
34ebe77
nexus method to create a system update + test for it
david-crespo Jan 5, 2023
4c59334
create_component_update() and working test
david-crespo Jan 5, 2023
7aa207c
other system update should not be associated with any component updates
david-crespo Jan 5, 2023
b9ac8b6
create updateable component, test for it
david-crespo Jan 5, 2023
c143f8a
make the unauthorized things pass, mediocrely
david-crespo Jan 5, 2023
c6f9dff
update iam roles policy test and nexus_tags.txt
david-crespo Jan 5, 2023
78e3fb7
make existing system update refresh endpoint match the rest
david-crespo Jan 7, 2023
8ffa99a
Merge branch 'main' into stub-update-api
david-crespo Jan 12, 2023
1eeaf4e
make version the PK of the system update, fetch by version instead of id
david-crespo Jan 12, 2023
c5b6264
remove id from system_update. horrible because it goes against the grain
david-crespo Jan 12, 2023
ffea521
Revert "remove id from system_update. horrible because it goes agains…
david-crespo Jan 12, 2023
190af7c
change comment: we're not getting rid of the ID. update openapi spec
david-crespo Jan 12, 2023
fde6e98
clean up around TODO comments, add SystemUpdateDeployment view, fix t…
david-crespo Jan 13, 2023
3ef6f38
can't give the params the same name as the view
david-crespo Jan 13, 2023
f8898a8
Merge branch 'main' into stub-update-api
david-crespo Jan 19, 2023
c145d60
Merge branch 'main' into stub-update-api
david-crespo Jan 19, 2023
2660a52
add update deployments table and list/view endpoints
david-crespo Jan 23, 2023
b3df99c
Merge main into stub-update-api
david-crespo Jan 23, 2023
9ec0773
fix clippy and tests
david-crespo Jan 23, 2023
e992960
Merge branch 'main' into stub-update-api
david-crespo Jan 25, 2023
3dc2bb0
plumb through UpdateStatus, SystemUpdateDeployment -> UpdateDeployment
david-crespo Jan 25, 2023
0746adf
version_sort column that lets us sort by version
david-crespo Jan 25, 2023
5a2b99f
validate that semver version has low enough numbers for our sort hack
david-crespo Jan 26, 2023
a28b371
add version_sort to updateable_component so we can get low/high for s…
david-crespo Jan 26, 2023
0d22dd0
better test to prove we're not doing normal string sort on versions
david-crespo Jan 26, 2023
53d7d03
component tree and component update tree are no longer trees
david-crespo Jan 26, 2023
07dea02
use a transaction, working integration test for system version endpoint
david-crespo Jan 26, 2023
05635bd
put verb first in nexus function names
david-crespo Jan 26, 2023
9575587
create_update_deployment (doesn't check if we're already updating)
david-crespo Jan 27, 2023
6cdfe40
fix ON CONFLICT by not doing that. add tests for version conflicts
david-crespo Jan 27, 2023
b7a0b93
change system update pk back to ID, exempt /system/version from auth …
david-crespo Jan 27, 2023
a1772af
updateable component should have both own version and system version
david-crespo Jan 28, 2023
f109cfe
don't blame buildomat. look inward
david-crespo Jan 30, 2023
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ ring = "0.16"
rustfmt-wrapper = "0.2"
samael = { git = "https://github.com/njaremko/samael", features = ["xmlsec"], branch = "master" }
schemars = "0.8.10"
semver = { version = "1.0.16", features = ["std", "serde"] }
serde = { version = "1.0", default-features = false, features = [ "derive" ] }
serde_derive = "1.0"
serde_json = "1.0.91"
Expand Down
1 change: 1 addition & 0 deletions nexus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ reqwest = { workspace = true, features = [ "json" ] }
ring.workspace = true
samael.workspace = true
schemars = { workspace = true, features = ["chrono", "uuid1"] }
semver.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_urlencoded.workspace = true
Expand Down
85 changes: 83 additions & 2 deletions nexus/src/external_api/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use super::{
console_api, device_auth, params, views,
views::{
GlobalImage, Group, IdentityProvider, Image, Organization, Project,
Rack, Role, Silo, Sled, Snapshot, SshKey, User, UserBuiltin, Vpc,
VpcRouter, VpcSubnet,
Rack, Role, Silo, Sled, Snapshot, SshKey, SystemUpdate,
SystemUpdateStatus, SystemVersionRange, SystemVersionStatus,
SystemVersionSteadyReason, User, UserBuiltin, Vpc, VpcRouter,
VpcSubnet,
},
};
use crate::authz;
Expand Down Expand Up @@ -72,6 +74,7 @@ use omicron_common::bail_unless;
use parse_display::Display;
use ref_cast::RefCast;
use schemars::JsonSchema;
// use semver;
use serde::Deserialize;
use serde::Serialize;
use std::sync::Arc;
Expand Down Expand Up @@ -274,6 +277,9 @@ pub fn external_api() -> NexusApiDescription {
api.register(system_image_delete)?;

api.register(updates_refresh)?;
api.register(system_update_status)?;
api.register(system_update_list)?;
api.register(system_update_view)?;

api.register(user_list)?;
api.register(silo_users_list)?;
Expand Down Expand Up @@ -5048,6 +5054,81 @@ async fn updates_refresh(
apictx.external_latencies.instrument_dropshot_handler(&rqctx, handler).await
}

/// List all updates
#[endpoint {
method = GET,
path = "/v1/system/update/status",
tags = ["system"],
}]
async fn system_update_status(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
) -> Result<HttpResponseOk<SystemUpdateStatus>, HttpError> {
let apictx = rqctx.context();
let _nexus = &apictx.nexus;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this is already on your radar, but we should consider a non-stub call before merging

let handler = async {
let _opctx = OpContext::for_external_api(&rqctx).await?;
Ok(HttpResponseOk(SystemUpdateStatus {
version_range: SystemVersionRange {
// low: semver::Version::new(0, 0, 1),
low: String::from("0.0.1"),
// high: semver::Version::new(0, 0, 2),
high: String::from("0.0.2"),
},
status: SystemVersionStatus::Steady {
reason: SystemVersionSteadyReason::Completed,
},
}))
};
apictx.external_latencies.instrument_dropshot_handler(&rqctx, handler).await
}

/// List all updates
#[endpoint {
method = GET,
path = "/v1/system/update/updates",
tags = ["system"],
}]
async fn system_update_list(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
) -> Result<HttpResponseOk<ResultsPage<SystemUpdate>>, HttpError> {
let apictx = rqctx.context();
let _nexus = &apictx.nexus;
let handler = async {
let _opctx = OpContext::for_external_api(&rqctx).await?;
Ok(HttpResponseOk(ResultsPage { items: vec![], next_page: None }))
};
apictx.external_latencies.instrument_dropshot_handler(&rqctx, handler).await
}

/// Path parameters for SystemUpdate requests
#[derive(Deserialize, JsonSchema)]
struct SystemUpdatePathParam {
update_id: Uuid,
}

/// View update
#[endpoint {
method = GET,
path = "/v1/system/update/updates/{update_id}",
tags = ["system"],
}]
async fn system_update_view(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
path_params: Path<SystemUpdatePathParam>,
) -> Result<HttpResponseOk<SystemUpdate>, HttpError> {
let apictx = rqctx.context();
let _nexus = &apictx.nexus;
let path = path_params.into_inner();
let handler = async {
let _opctx = OpContext::for_external_api(&rqctx).await?;
Ok(HttpResponseOk(SystemUpdate {
id: path.update_id,
version: String::from("1.0.0"),
}))
};
apictx.external_latencies.instrument_dropshot_handler(&rqctx, handler).await
}

// Sagas

/// List sagas
Expand Down
3 changes: 3 additions & 0 deletions nexus/tests/output/nexus_tags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ system_image_delete /system/images/{image_name}
system_image_list /system/images
system_image_view /system/images/{image_name}
system_image_view_by_id /system/by-id/images/{id}
system_update_list /v1/system/update/updates
system_update_status /v1/system/update/status
system_update_view /v1/system/update/updates/{update_id}
system_user_list /system/user
system_user_view /system/user/{user_name}
updates_refresh /system/updates/refresh
Expand Down
1 change: 1 addition & 0 deletions nexus/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ base64.workspace = true
openssl.workspace = true
openssl-sys.workspace = true
openssl-probe.workspace = true
semver.workspace = true
schemars = { workspace = true, features = ["chrono", "uuid1"] }
serde.workspace = true
serde_json.workspace = true
Expand Down
45 changes: 45 additions & 0 deletions nexus/types/src/external_api/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use omicron_common::api::external::{
ObjectIdentity, RoleName,
};
use schemars::JsonSchema;
// use semver;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::net::SocketAddrV6;
Expand Down Expand Up @@ -412,3 +413,47 @@ pub struct DeviceAccessTokenGrant {
pub enum DeviceAccessTokenType {
Bearer,
}

// SYSTEM UPDATES

#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub struct SystemVersionRange {
// TODO: if we want to use semver::Version, I think we have to newtype it
// in order to implement JsonSchema. ew
// pub low: semver::Version,
// pub high: semver::Version,
pub low: String,
pub high: String,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smklein if we want to use semver::Version here, which sounds sensible, we need to wrap it and impl JsonSchema on that. Correct?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so - looks like someone already started work on this here: GREsau/schemars#195

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good timing. I looked but apparently in the wrong place.


#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SystemVersionSteadyReason {
Completed,
Stopped,
Failed,
}

#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SystemVersionStatus {
Updating {
// target: semver::Version
target: String,
},
Steady {
reason: SystemVersionSteadyReason,
},
}

#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub struct SystemUpdateStatus {
pub version_range: SystemVersionRange,
pub status: SystemVersionStatus,
}

#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub struct SystemUpdate {
pub id: Uuid,
pub version: String,
}
Loading