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

PoC - Absorbing views and params into Nexus #191

Closed
wants to merge 7 commits into from
Closed
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
1 change: 1 addition & 0 deletions Cargo.lock

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

38 changes: 0 additions & 38 deletions omicron-common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,44 +514,6 @@ pub struct IdentityMetadataUpdateParams {
* Specific API resources
*/

/*
* PROJECTS
*/

/**
* Client view of an [`Project`]
*/
#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Project {
/*
* TODO-correctness is flattening here (and in all the other types) the
* intent in RFD 4?
*/
#[serde(flatten)]
pub identity: IdentityMetadata,
}

/**
* Create-time parameters for an [`Project`]
*/
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProjectCreateParams {
#[serde(flatten)]
pub identity: IdentityMetadataCreateParams,
}

/**
* Updateable properties of an [`Project`]
*/
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProjectUpdateParams {
#[serde(flatten)]
pub identity: IdentityMetadataUpdateParams,
}

/*
* INSTANCES
*/
Expand Down
3 changes: 3 additions & 0 deletions omicron-nexus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ structopt = "0.3"
thiserror = "1.0"
toml = "0.5.6"

[dependencies.api_identity]
path = "../api_identity"

[dependencies.chrono]
version = "0.4"
features = [ "serde" ]
Expand Down
3 changes: 2 additions & 1 deletion omicron-nexus/src/db/datastore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use super::sql_operations::sql_insert_unique;
use super::sql_operations::sql_insert_unique_idempotent_and_fetch;
use super::sql_operations::sql_update_precond;
use crate::db;
use crate::external::params;

pub struct DataStore {
pool: Arc<Pool>,
Expand Down Expand Up @@ -171,7 +172,7 @@ impl DataStore {
pub async fn project_update(
&self,
project_name: &Name,
update_params: &api::external::ProjectUpdateParams,
update_params: &params::ProjectUpdate,
) -> UpdateResult<db::model::Project> {
let client = self.pool.acquire().await?;
let now = Utc::now();
Expand Down
25 changes: 5 additions & 20 deletions omicron-nexus/src/db/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ pub struct IdentityMetadata {
}

impl IdentityMetadata {
fn new(id: Uuid, params: external::IdentityMetadataCreateParams) -> Self {
pub fn new(
id: Uuid,
params: external::IdentityMetadataCreateParams,
) -> Self {
let now = Utc::now();
Self {
id,
Expand Down Expand Up @@ -138,16 +141,10 @@ impl TryFrom<&tokio_postgres::Row> for IdentityMetadata {

/// Describes a project within the database.
pub struct Project {
identity: IdentityMetadata,
pub identity: IdentityMetadata,
}

impl Project {
/// Creates a new database Project object.
pub fn new(params: &external::ProjectCreateParams) -> Self {
let id = Uuid::new_v4();
Self { identity: IdentityMetadata::new(id, params.identity.clone()) }
}

pub fn name(&self) -> &str {
self.identity.name.as_str()
}
Expand All @@ -157,19 +154,7 @@ impl Project {
}
}

/// Conversion to the internal API type.
impl Into<external::Project> for Project {
fn into(self) -> external::Project {
external::Project { identity: self.identity.into() }
}
}

/// Conversion from the internal API type.
impl From<external::Project> for Project {
fn from(project: external::Project) -> Self {
Self { identity: project.identity.into() }
}
}

/// Serialization to DB.
impl SqlSerialize for Project {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
* Handler functions (entrypoints) for external HTTP APIs
*/

use super::ServerContext;
use crate::context::ServerContext;
use crate::db;

use super::params;
use super::views;
use dropshot::endpoint;
use dropshot::ApiDescription;
use dropshot::HttpError;
Expand Down Expand Up @@ -38,9 +40,6 @@ use omicron_common::api::external::Instance;
use omicron_common::api::external::InstanceCreateParams;
use omicron_common::api::external::Name;
use omicron_common::api::external::PaginationOrder;
use omicron_common::api::external::Project;
use omicron_common::api::external::ProjectCreateParams;
use omicron_common::api::external::ProjectUpdateParams;
use omicron_common::api::external::Rack;
use omicron_common::api::external::Saga;
use omicron_common::api::external::Sled;
Expand Down Expand Up @@ -156,7 +155,7 @@ pub fn external_api() -> NexusApiDescription {
async fn projects_get(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
query_params: Query<PaginatedByNameOrId>,
) -> Result<HttpResponseOk<ResultsPage<Project>>, HttpError> {
) -> Result<HttpResponseOk<ResultsPage<views::Project>>, HttpError> {
let apictx = rqctx.context();
let nexus = &apictx.nexus;
let query = query_params.into_inner();
Expand All @@ -176,7 +175,7 @@ async fn projects_get(
};

let view_list =
to_list::<db::model::Project, Project>(project_stream).await;
to_list::<db::model::Project, views::Project>(project_stream).await;
Ok(HttpResponseOk(ScanByNameOrId::results_page(&query, view_list)?))
}

Expand All @@ -189,8 +188,8 @@ async fn projects_get(
}]
async fn projects_post(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
new_project: TypedBody<ProjectCreateParams>,
) -> Result<HttpResponseCreated<Project>, HttpError> {
new_project: TypedBody<params::ProjectCreate>,
) -> Result<HttpResponseCreated<views::Project>, HttpError> {
let apictx = rqctx.context();
let nexus = &apictx.nexus;
let project = nexus.project_create(&new_project.into_inner()).await?;
Expand All @@ -216,7 +215,7 @@ struct ProjectPathParam {
async fn projects_get_project(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
path_params: Path<ProjectPathParam>,
) -> Result<HttpResponseOk<Project>, HttpError> {
) -> Result<HttpResponseOk<views::Project>, HttpError> {
let apictx = rqctx.context();
let nexus = &apictx.nexus;
let path = path_params.into_inner();
Expand Down Expand Up @@ -260,8 +259,8 @@ async fn projects_delete_project(
async fn projects_put_project(
rqctx: Arc<RequestContext<Arc<ServerContext>>>,
path_params: Path<ProjectPathParam>,
updated_project: TypedBody<ProjectUpdateParams>,
) -> Result<HttpResponseOk<Project>, HttpError> {
updated_project: TypedBody<params::ProjectUpdate>,
) -> Result<HttpResponseOk<views::Project>, HttpError> {
let apictx = rqctx.context();
let nexus = &apictx.nexus;
let path = path_params.into_inner();
Expand Down
3 changes: 3 additions & 0 deletions omicron-nexus/src/external/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod http_entrypoints;
pub mod params;
pub mod views;
36 changes: 36 additions & 0 deletions omicron-nexus/src/external/params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::db::model;
use omicron_common::api::external::IdentityMetadataCreateParams;
use omicron_common::api::external::IdentityMetadataUpdateParams;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;

/**
* Create-time parameters for an [`Project`]
*/
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProjectCreate {
#[serde(flatten)]
pub identity: IdentityMetadataCreateParams,
}

impl From<&ProjectCreate> for model::Project {
fn from(params: &ProjectCreate) -> Self {
let id = Uuid::new_v4();
Self {
identity: model::IdentityMetadata::new(id, params.identity.clone()),
}
}
}

/**
* Updateable properties of an [`Project`]
*/
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProjectUpdate {
#[serde(flatten)]
pub identity: IdentityMetadataUpdateParams,
}
33 changes: 33 additions & 0 deletions omicron-nexus/src/external/views.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*!
* Views are the types of API Responses. Mostly they will be straightforward
* transformations of models (which can use From), but some may be composites
* of more than one model and therefore require a special constructor.
*/

use crate::db;
use api_identity::ObjectIdentity;
use omicron_common::api::external::IdentityMetadata;
use omicron_common::api::external::ObjectIdentity;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;

/**
* Client view of an [`Project`]
*/
#[derive(ObjectIdentity, Clone, Debug, Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Project {
/*
* TODO-correctness is flattening here (and in all the other types) the
* intent in RFD 4?
*/
#[serde(flatten)]
pub identity: IdentityMetadata,
}

impl From<db::model::Project> for Project {
fn from(project: db::model::Project) -> Self {
Self { identity: project.identity.into() }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Handler functions (entrypoints) for HTTP APIs internal to the control plane
*/
use super::ServerContext;
use super::super::ServerContext;

use dropshot::endpoint;
use dropshot::ApiDescription;
Expand Down
1 change: 1 addition & 0 deletions omicron-nexus/src/internal/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod http_entrypoints;
8 changes: 4 additions & 4 deletions omicron-nexus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
mod config;
mod context;
pub mod db; // Public only for some documentation examples
mod http_entrypoints_external;
mod http_entrypoints_internal;
pub mod external;
mod internal;
mod nexus;
mod saga_interface;
mod sagas;
Expand All @@ -26,8 +26,8 @@ pub use context::ServerContext;
pub use nexus::Nexus;
pub use nexus::TestInterfaces;

use http_entrypoints_external::external_api;
use http_entrypoints_internal::internal_api;
use external::http_entrypoints::external_api;
use internal::http_entrypoints::internal_api;

use slog::Logger;
use std::sync::Arc;
Expand Down
12 changes: 5 additions & 7 deletions omicron-nexus/src/nexus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

use crate::db;
use crate::external::params;
use crate::saga_interface::SagaContext;
use crate::sagas;
use anyhow::Context;
Expand All @@ -27,8 +28,6 @@ use omicron_common::api::external::InstanceState;
use omicron_common::api::external::ListResult;
use omicron_common::api::external::LookupResult;
use omicron_common::api::external::Name;
use omicron_common::api::external::ProjectCreateParams;
use omicron_common::api::external::ProjectUpdateParams;
use omicron_common::api::external::ResourceType;
use omicron_common::api::external::UpdateResult;
use omicron_common::api::external::Vpc;
Expand Down Expand Up @@ -295,12 +294,11 @@ impl Nexus {

pub async fn project_create(
&self,
new_project: &ProjectCreateParams,
params: &params::ProjectCreate,
) -> CreateResult<db::model::Project> {
// Create a project.
let db_project = db::model::Project::new(new_project);
let project: db::model::Project =
self.db_datastore.project_create(&db_project).await?;
self.db_datastore.project_create(&params.into()).await?;
// TODO: We probably want to have "project creation" and "default VPC
// creation" co-located within a saga for atomicity.
//
Expand Down Expand Up @@ -356,9 +354,9 @@ impl Nexus {
pub async fn project_update(
&self,
name: &Name,
new_params: &ProjectUpdateParams,
params: &params::ProjectUpdate,
) -> UpdateResult<db::model::Project> {
self.db_datastore.project_update(name, new_params).await
self.db_datastore.project_update(name, params).await
}

/*
Expand Down
8 changes: 4 additions & 4 deletions omicron-nexus/tests/output/nexus-openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProjectCreateParams"
"$ref": "#/components/schemas/ProjectCreate"
}
}
},
Expand Down Expand Up @@ -291,7 +291,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProjectUpdateParams"
"$ref": "#/components/schemas/ProjectUpdate"
}
}
},
Expand Down Expand Up @@ -1729,7 +1729,7 @@
"timeModified"
]
},
"ProjectCreateParams": {
"ProjectCreate": {
"description": "Create-time parameters for an [`Project`]",
"type": "object",
"properties": {
Expand Down Expand Up @@ -1765,7 +1765,7 @@
"items"
]
},
"ProjectUpdateParams": {
"ProjectUpdate": {
"description": "Updateable properties of an [`Project`]",
"type": "object",
"properties": {
Expand Down
Loading