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

Network Operator BGP API improvements #6362

Merged
merged 15 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1895,7 +1895,8 @@ allow_tables_to_appear_in_same_query!(

allow_tables_to_appear_in_same_query!(
switch_port,
switch_port_settings_bgp_peer_config
switch_port_settings_bgp_peer_config,
bgp_config
);

allow_tables_to_appear_in_same_query!(disk, virtual_provisioning_resource);
Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::collections::BTreeMap;
///
/// This must be updated when you change the database schema. Refer to
/// schema/crdb/README.adoc in the root of this repository for details.
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(87, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(88, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::new(|| {
// | leaving the first copy as an example for the next person.
// v
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
KnownVersion::new(88, "lookup-bgp-config-by-asn"),
KnownVersion::new(87, "add-clickhouse-server-enum-variants"),
KnownVersion::new(86, "snapshot-replacement"),
KnownVersion::new(85, "add-migrations-by-time-created-index"),
Expand Down
673 changes: 492 additions & 181 deletions nexus/db-queries/src/db/datastore/bgp.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ impl DataStore {
}
}

#[derive(Clone, Copy, Debug)]
pub enum UpdatePrecondition<T> {
DontCare,
Null,
Expand Down
285 changes: 200 additions & 85 deletions nexus/db-queries/src/db/datastore/switch_port.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ impl BackgroundTask for SwitchPortSettingsManager {
if !bgp_announce_prefixes.contains_key(&bgp_config.bgp_announce_set_id) {
let announcements = match self
.datastore
.bgp_announce_list(
.bgp_announcement_list(
opctx,
&params::BgpAnnounceSetSelector {
name_or_id: bgp_config
Expand Down
17 changes: 13 additions & 4 deletions nexus/src/app/bgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ impl super::Nexus {
Ok(result)
}

pub async fn bgp_announce_list(
pub async fn bgp_announce_set_list(
&self,
opctx: &OpContext,
sel: &params::BgpAnnounceSetSelector,
) -> ListResultVec<BgpAnnouncement> {
pagparams: &PaginatedBy<'_>,
) -> ListResultVec<BgpAnnounceSet> {
opctx.authorize(authz::Action::Read, &authz::FLEET).await?;
self.db_datastore.bgp_announce_list(opctx, sel).await
self.db_datastore.bgp_announce_set_list(opctx, pagparams).await
}

pub async fn bgp_delete_announce_set(
Expand All @@ -88,6 +88,15 @@ impl super::Nexus {
Ok(result)
}

pub async fn bgp_announcement_list(
&self,
opctx: &OpContext,
sel: &params::BgpAnnounceSetSelector,
) -> ListResultVec<BgpAnnouncement> {
opctx.authorize(authz::Action::Read, &authz::FLEET).await?;
self.db_datastore.bgp_announcement_list(opctx, sel).await
}

pub async fn bgp_peer_status(
&self,
opctx: &OpContext,
Expand Down
62 changes: 51 additions & 11 deletions nexus/src/external_api/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ pub(crate) fn external_api() -> NexusApiDescription {
api.register(networking_bgp_announce_set_delete)?;
api.register(networking_bgp_message_history)?;

api.register(networking_bgp_announcement_list)?;

api.register(networking_bfd_enable)?;
api.register(networking_bfd_disable)?;
api.register(networking_bfd_status)?;
Expand Down Expand Up @@ -4062,7 +4064,7 @@ async fn networking_bgp_config_delete(
/// set with the one specified.
#[endpoint {
method = PUT,
path = "/v1/system/networking/bgp-announce",
path = "/v1/system/networking/bgp-announce-set",
tags = ["system/networking"],
}]
async fn networking_bgp_announce_set_update(
Expand All @@ -4084,24 +4086,28 @@ async fn networking_bgp_announce_set_update(
.await
}

//TODO pagination? the normal by-name/by-id stuff does not work here
/// Get originated routes for a BGP configuration
/// List BGP announce sets
#[endpoint {
method = GET,
path = "/v1/system/networking/bgp-announce",
path = "/v1/system/networking/bgp-announce-set",
tags = ["system/networking"],
}]
async fn networking_bgp_announce_set_list(
rqctx: RequestContext<ApiContext>,
query_params: Query<params::BgpAnnounceSetSelector>,
) -> Result<HttpResponseOk<Vec<BgpAnnouncement>>, HttpError> {
query_params: Query<
PaginatedByNameOrId<params::OptionalBgpAnnounceSetSelector>,
>,
) -> Result<HttpResponseOk<Vec<BgpAnnounceSet>>, HttpError> {
let apictx = rqctx.context();
let handler = async {
let nexus = &apictx.context.nexus;
let sel = query_params.into_inner();
let query = query_params.into_inner();
let pag_params = data_page_params_for(&rqctx, &query)?;
let scan_params = ScanByNameOrId::from_query(&query)?;
let paginated_by = name_or_id_pagination(&pag_params, scan_params)?;
let opctx = crate::context::op_context_for_external_api(&rqctx).await?;
let result = nexus
.bgp_announce_list(&opctx, &sel)
.bgp_announce_set_list(&opctx, &paginated_by)
.await?
.into_iter()
.map(|p| p.into())
Expand All @@ -4118,17 +4124,17 @@ async fn networking_bgp_announce_set_list(
/// Delete BGP announce set
#[endpoint {
method = DELETE,
path = "/v1/system/networking/bgp-announce",
path = "/v1/system/networking/bgp-announce-set/{name_or_id}",
tags = ["system/networking"],
}]
async fn networking_bgp_announce_set_delete(
rqctx: RequestContext<ApiContext>,
selector: Query<params::BgpAnnounceSetSelector>,
path_params: Path<params::BgpAnnounceSetSelector>,
) -> Result<HttpResponseUpdatedNoContent, HttpError> {
let apictx = rqctx.context();
let handler = async {
let nexus = &apictx.context.nexus;
let sel = selector.into_inner();
let sel = path_params.into_inner();
let opctx = crate::context::op_context_for_external_api(&rqctx).await?;
nexus.bgp_delete_announce_set(&opctx, &sel).await?;
Ok(HttpResponseUpdatedNoContent {})
Expand All @@ -4140,6 +4146,40 @@ async fn networking_bgp_announce_set_delete(
.await
}

// TODO: is pagination necessary here? How large do we expect the list of
// announcements to become in real usage?
/// Get originated routes for a specified BGP announce set
#[endpoint {
method = GET,
path = "/v1/system/networking/bgp-announce-set/{name_or_id}/announcement",
tags = ["system/networking"],
}]
async fn networking_bgp_announcement_list(
rqctx: RequestContext<ApiContext>,
path_params: Path<params::BgpAnnounceSetSelector>,
) -> Result<HttpResponseOk<Vec<BgpAnnouncement>>, HttpError> {
let apictx = rqctx.context();
let handler = async {
let nexus = &apictx.context.nexus;
let sel = path_params.into_inner();
let opctx = crate::context::op_context_for_external_api(&rqctx).await?;

let result = nexus
.bgp_announcement_list(&opctx, &sel)
.await?
.into_iter()
.map(|p| p.into())
.collect();

Ok(HttpResponseOk(result))
};
apictx
.context
.external_latencies
.instrument_dropshot_handler(&rqctx, handler)
.await
}

/// Enable a BFD session
#[endpoint {
method = POST,
Expand Down
26 changes: 24 additions & 2 deletions nexus/tests/integration_tests/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ pub static DEMO_BGP_CONFIG: Lazy<params::BgpConfigCreate> =
shaper: None,
});
pub const DEMO_BGP_ANNOUNCE_SET_URL: &'static str =
"/v1/system/networking/bgp-announce?name_or_id=a-bag-of-addrs";
"/v1/system/networking/bgp-announce-set";
pub static DEMO_BGP_ANNOUNCE: Lazy<params::BgpAnnounceSetCreate> =
Lazy::new(|| params::BgpAnnounceSetCreate {
identity: IdentityMetadataCreateParams {
Expand All @@ -591,6 +591,10 @@ pub static DEMO_BGP_ANNOUNCE: Lazy<params::BgpAnnounceSetCreate> =
network: "10.0.0.0/16".parse().unwrap(),
}],
});
pub const DEMO_BGP_ANNOUNCE_SET_DELETE_URL: &'static str =
"/v1/system/networking/bgp-announce-set/a-bag-of-addrs";
pub const DEMO_BGP_ANNOUNCEMENT_URL: &'static str =
"/v1/system/networking/bgp-announce-set/a-bag-of-addrs/announcement";
pub const DEMO_BGP_STATUS_URL: &'static str =
"/v1/system/networking/bgp-status";
pub const DEMO_BGP_ROUTES_IPV4_URL: &'static str =
Expand Down Expand Up @@ -2290,6 +2294,7 @@ pub static VERIFY_ENDPOINTS: Lazy<Vec<VerifyEndpoint>> = Lazy::new(|| {
AllowedMethod::GetNonexistent
],
},

VerifyEndpoint {
url: &DEMO_BGP_CONFIG_CREATE_URL,
visibility: Visibility::Public,
Expand All @@ -2311,11 +2316,28 @@ pub static VERIFY_ENDPOINTS: Lazy<Vec<VerifyEndpoint>> = Lazy::new(|| {
AllowedMethod::Put(
serde_json::to_value(&*DEMO_BGP_ANNOUNCE).unwrap(),
),
AllowedMethod::GetNonexistent,
AllowedMethod::Get,
],
},

VerifyEndpoint {
url: &DEMO_BGP_ANNOUNCE_SET_DELETE_URL,
visibility: Visibility::Public,
unprivileged_access: UnprivilegedAccess::None,
allowed_methods: vec![
AllowedMethod::Delete
],
},

VerifyEndpoint {
url: &DEMO_BGP_ANNOUNCEMENT_URL,
visibility: Visibility::Public,
unprivileged_access: UnprivilegedAccess::None,
allowed_methods: vec![
AllowedMethod::GetNonexistent,
],
},

VerifyEndpoint {
url: &DEMO_BGP_STATUS_URL,
visibility: Visibility::Public,
Expand Down
2 changes: 1 addition & 1 deletion nexus/tests/integration_tests/switch_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) {

NexusRequest::objects_post(
client,
"/v1/system/networking/bgp-announce",
"/v1/system/networking/bgp-announce-set",
&announce_set,
)
.authn_as(AuthnMode::PrivilegedUser)
Expand Down
7 changes: 4 additions & 3 deletions nexus/tests/output/nexus_tags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,10 @@ networking_allow_list_view GET /v1/system/networking/allow-li
networking_bfd_disable POST /v1/system/networking/bfd-disable
networking_bfd_enable POST /v1/system/networking/bfd-enable
networking_bfd_status GET /v1/system/networking/bfd-status
networking_bgp_announce_set_delete DELETE /v1/system/networking/bgp-announce
networking_bgp_announce_set_list GET /v1/system/networking/bgp-announce
networking_bgp_announce_set_update PUT /v1/system/networking/bgp-announce
networking_bgp_announce_set_delete DELETE /v1/system/networking/bgp-announce-set/{name_or_id}
networking_bgp_announce_set_list GET /v1/system/networking/bgp-announce-set
networking_bgp_announce_set_update PUT /v1/system/networking/bgp-announce-set
networking_bgp_announcement_list GET /v1/system/networking/bgp-announce-set/{name_or_id}/announcement
networking_bgp_config_create POST /v1/system/networking/bgp
networking_bgp_config_delete DELETE /v1/system/networking/bgp
networking_bgp_config_list GET /v1/system/networking/bgp
Expand Down
7 changes: 7 additions & 0 deletions nexus/types/src/external_api/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,13 @@ pub struct BgpAnnounceSetCreate {
pub announcement: Vec<BgpAnnouncementCreate>,
}

/// Optionally select a BGP announce set by a name or id.
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
pub struct OptionalBgpAnnounceSetSelector {
/// A name or id to use when s electing BGP port settings
pub name_or_id: Option<NameOrId>,
}

/// Select a BGP announce set by a name or id.
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq)]
pub struct BgpAnnounceSetSelector {
Expand Down
Loading
Loading