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

[oximeter] turn API into a trait #6130

Merged
merged 1 commit into from
Jul 22, 2024
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
15 changes: 15 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ members = [
"nexus/test-utils-macros",
"nexus/test-utils",
"nexus/types",
"oximeter/api",
"oximeter/collector",
"oximeter/db",
"oximeter/impl",
Expand Down Expand Up @@ -158,6 +159,7 @@ default-members = [
"nexus/test-utils-macros",
"nexus/test-utils",
"nexus/types",
"oximeter/api",
"oximeter/collector",
"oximeter/db",
"oximeter/impl",
Expand Down Expand Up @@ -397,6 +399,7 @@ opte-ioctl = { git = "https://github.com/oxidecomputer/opte", rev = "3dc9a3dd8d3
oso = "0.27"
owo-colors = "4.0.0"
oximeter = { path = "oximeter/oximeter" }
oximeter-api = { path = "oximeter/api" }
oximeter-client = { path = "clients/oximeter-client" }
oximeter-db = { path = "oximeter/db/", default-features = false }
oximeter-collector = { path = "oximeter/collector" }
Expand Down
1 change: 1 addition & 0 deletions dev-tools/openapi-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ omicron-workspace-hack.workspace = true
openapiv3.workspace = true
openapi-lint.workspace = true
owo-colors.workspace = true
oximeter-api.workspace = true
serde_json.workspace = true
similar.workspace = true
supports-color.workspace = true
Expand Down
10 changes: 10 additions & 0 deletions dev-tools/openapi-manager/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ pub fn all_apis() -> Vec<ApiSpec> {
filename: "nexus-internal.json",
extra_validation: None,
},
ApiSpec {
title: "Oxide Oximeter API",
version: "0.0.1",
description: "API for interacting with oximeter",
boundary: ApiBoundary::Internal,
api_description:
oximeter_api::oximeter_api_mod::stub_api_description,
filename: "oximeter.json",
extra_validation: None,
},
ApiSpec {
title: "Oxide Technician Port Control Service",
version: "0.0.1",
Expand Down
4 changes: 4 additions & 0 deletions openapi/oximeter.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"paths": {
"/info": {
"get": {
"summary": "Return identifying information about this collector.",
"operationId": "collector_info",
"responses": {
"200": {
Expand All @@ -35,6 +36,7 @@
},
"/producers": {
"get": {
"summary": "List all producers.",
"operationId": "producers_list",
"parameters": [
{
Expand Down Expand Up @@ -81,6 +83,7 @@
}
},
"post": {
"summary": "Handle a request from Nexus to register a new producer with this collector.",
"operationId": "producers_post",
"requestBody": {
"content": {
Expand All @@ -107,6 +110,7 @@
},
"/producers/{producer_id}": {
"delete": {
"summary": "Delete a producer by ID.",
"operationId": "producer_delete",
"parameters": [
{
Expand Down
16 changes: 16 additions & 0 deletions oximeter/api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "oximeter-api"
version = "0.1.0"
edition = "2021"

[lints]
workspace = true

[dependencies]
chrono.workspace = true
dropshot.workspace = true
omicron-common.workspace = true
omicron-workspace-hack.workspace = true
schemars.workspace = true
serde.workspace = true
uuid.workspace = true
79 changes: 79 additions & 0 deletions oximeter/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use chrono::{DateTime, Utc};
use dropshot::{
EmptyScanParams, HttpError, HttpResponseDeleted, HttpResponseOk,
HttpResponseUpdatedNoContent, PaginationParams, Query, RequestContext,
ResultsPage, TypedBody,
};
use omicron_common::api::internal::nexus::ProducerEndpoint;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[dropshot::api_description {
module = "oximeter_api_mod",
}]
pub trait OximeterApi {
type Context;

/// Handle a request from Nexus to register a new producer with this collector.
#[endpoint {
method = POST,
path = "/producers",
}]
async fn producers_post(
request_context: RequestContext<Self::Context>,
body: TypedBody<ProducerEndpoint>,
) -> Result<HttpResponseUpdatedNoContent, HttpError>;

/// List all producers.
#[endpoint {
method = GET,
path = "/producers",
}]
async fn producers_list(
request_context: RequestContext<Self::Context>,
query: Query<PaginationParams<EmptyScanParams, ProducerPage>>,
) -> Result<HttpResponseOk<ResultsPage<ProducerEndpoint>>, HttpError>;

/// Delete a producer by ID.
#[endpoint {
method = DELETE,
path = "/producers/{producer_id}",
}]
async fn producer_delete(
request_context: RequestContext<Self::Context>,
path: dropshot::Path<ProducerIdPathParams>,
) -> Result<HttpResponseDeleted, HttpError>;

/// Return identifying information about this collector.
#[endpoint {
method = GET,
path = "/info",
}]
async fn collector_info(
request_context: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<CollectorInfo>, HttpError>;
}

/// Parameters for paginating the list of producers.
#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, Serialize)]
pub struct ProducerPage {
pub id: Uuid,
}

#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, Serialize)]
pub struct ProducerIdPathParams {
pub producer_id: Uuid,
}

#[derive(Clone, Copy, Debug, Deserialize, JsonSchema, Serialize)]
pub struct CollectorInfo {
/// The collector's UUID.
pub id: Uuid,
/// Last time we refreshed our producer list with Nexus.
pub last_refresh: Option<DateTime<Utc>>,
}
1 change: 1 addition & 0 deletions oximeter/collector/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ internal-dns.workspace = true
nexus-types.workspace = true
omicron-common.workspace = true
oximeter.workspace = true
oximeter-api.workspace = true
oximeter-client.workspace = true
oximeter-db.workspace = true
rand.workspace = true
Expand Down
17 changes: 0 additions & 17 deletions oximeter/collector/src/bin/oximeter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use anyhow::{anyhow, Context};
use clap::Parser;
use omicron_common::cmd::fatal;
use omicron_common::cmd::CmdError;
use oximeter_collector::oximeter_api;
use oximeter_collector::standalone_nexus_api;
use oximeter_collector::Config;
use oximeter_collector::Oximeter;
Expand All @@ -23,16 +22,6 @@ use std::net::SocketAddrV6;
use std::path::PathBuf;
use uuid::Uuid;

pub fn run_openapi() -> Result<(), String> {
oximeter_api()
.openapi("Oxide Oximeter API", "0.0.1")
.description("API for interacting with oximeter")
.contact_url("https://oxide.computer")
.contact_email("[email protected]")
.write(&mut std::io::stdout())
.map_err(|e| e.to_string())
}

pub fn run_standalone_openapi() -> Result<(), String> {
standalone_nexus_api()
.openapi("Oxide Nexus API", "0.0.1")
Expand All @@ -47,9 +36,6 @@ pub fn run_standalone_openapi() -> Result<(), String> {
#[derive(Parser)]
#[clap(name = "oximeter", about = "See README.adoc for more information")]
enum Args {
/// Print the external OpenAPI Spec document and exit
Openapi,

/// Start an Oximeter server
Run {
/// Path to TOML file with configuration for the server
Expand Down Expand Up @@ -133,9 +119,6 @@ async fn main() {
async fn do_run() -> Result<(), CmdError> {
let args = Args::parse();
match args {
Args::Openapi => {
run_openapi().map_err(|err| CmdError::Failure(anyhow!(err)))
}
Args::Run { config_file, id, address } => {
let config = Config::from_file(config_file).unwrap();
let args = OximeterArguments { id, address };
Expand Down
Loading
Loading