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

add API endpoint for BGP announce set modification #6024

Merged
merged 8 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
12 changes: 6 additions & 6 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ macaddr = { version = "1.0.1", features = ["serde_std"] }
maplit = "1.0.2"
mockall = "0.12"
newtype_derive = "0.1.6"
mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "6e0a232fd0b443c19f61f94bf02b7695505aa8e3" }
ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "6e0a232fd0b443c19f61f94bf02b7695505aa8e3" }
mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "8c5806d0bb3ac38efec716e22fe7cdcd424de09c" }
ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "8c5806d0bb3ac38efec716e22fe7cdcd424de09c" }
multimap = "0.10.0"
nexus-auth = { path = "nexus/auth" }
nexus-client = { path = "clients/nexus-client" }
Expand Down
72 changes: 72 additions & 0 deletions nexus/db-queries/src/db/datastore/bgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,78 @@ impl DataStore {
})
}

pub async fn bgp_update_announce_set(
&self,
opctx: &OpContext,
announce: &params::BgpAnnounceSetCreate,
) -> CreateResult<(BgpAnnounceSet, Vec<BgpAnnouncement>)> {
use db::schema::bgp_announce_set::dsl as announce_set_dsl;
use db::schema::bgp_announcement::dsl as bgp_announcement_dsl;

let conn = self.pool_connection_authorized(opctx).await?;

self.transaction_retry_wrapper("bgp_update_announce_set")
.transaction(&conn, |conn| async move {
let bas: BgpAnnounceSet = announce.clone().into();

// ensure the announce set exists
let found_as: Option<BgpAnnounceSet> =
announce_set_dsl::bgp_announce_set
.filter(
announce_set_dsl::name
.eq(Name::from(bas.name().clone())),
)
.filter(announce_set_dsl::time_deleted.is_null())
.select(BgpAnnounceSet::as_select())
.limit(1)
.first_async(&conn)
.await
.ok();

let db_as = match found_as {
Some(v) => v,
None => {
diesel::insert_into(announce_set_dsl::bgp_announce_set)
.values(bas.clone())
.returning(BgpAnnounceSet::as_returning())
.get_result_async::<BgpAnnounceSet>(&conn)
.await?
}
};

// clear existing announcements
diesel::delete(bgp_announcement_dsl::bgp_announcement)
.filter(
bgp_announcement_dsl::announce_set_id.eq(db_as.id()),
)
.execute_async(&conn)
.await?;

// repopulate announcements
let mut db_annoucements = Vec::new();
for a in &announce.announcement {
let an = BgpAnnouncement {
announce_set_id: db_as.id(),
address_lot_block_id: bas.identity.id,
network: a.network.into(),
};
let db_an = diesel::insert_into(
bgp_announcement_dsl::bgp_announcement,
)
.values(an.clone())
.returning(BgpAnnouncement::as_returning())
.get_result_async::<BgpAnnouncement>(&conn)
.await?;

db_annoucements.push(db_an);
}

Ok((db_as, db_annoucements))
})
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))
}

pub async fn bgp_create_announce_set(
&self,
opctx: &OpContext,
Expand Down
38 changes: 31 additions & 7 deletions nexus/db-queries/src/db/datastore/switch_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,7 @@ impl DataStore {
}
}
else {
public_error_from_diesel(
e,
ErrorHandler::Conflict(
ResourceType::SwitchPortSettings,
params.identity.name.as_str(),
),
)
public_error_from_diesel(e, ErrorHandler::Server)
}
})
}
Expand Down Expand Up @@ -1451,6 +1445,36 @@ async fn do_switch_port_settings_delete(
.execute_async(conn)
.await?;

// delete allowed exports
use db::schema::switch_port_settings_bgp_peer_config_allow_export as allow_export;
use db::schema::switch_port_settings_bgp_peer_config_allow_export::dsl as allow_export_dsl;
diesel::delete(
allow_export_dsl::switch_port_settings_bgp_peer_config_allow_export,
)
.filter(allow_export::port_settings_id.eq(id))
.execute_async(conn)
.await?;

// delete allowed imports
use db::schema::switch_port_settings_bgp_peer_config_allow_import as allow_import;
use db::schema::switch_port_settings_bgp_peer_config_allow_import::dsl as allow_import_dsl;
diesel::delete(
allow_import_dsl::switch_port_settings_bgp_peer_config_allow_import,
)
.filter(allow_import::port_settings_id.eq(id))
.execute_async(conn)
.await?;

// delete communities
use db::schema::switch_port_settings_bgp_peer_config_communities as bgp_communities;
use db::schema::switch_port_settings_bgp_peer_config_communities::dsl as bgp_communities_dsl;
diesel::delete(
bgp_communities_dsl::switch_port_settings_bgp_peer_config_communities,
)
.filter(bgp_communities::port_settings_id.eq(id))
.execute_async(conn)
.await?;

// delete address configs
use db::schema::switch_port_settings_address_config::{
self as address_config, dsl as address_config_dsl,
Expand Down
8 changes: 6 additions & 2 deletions nexus/src/app/bgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,18 @@ impl super::Nexus {
Ok(result)
}

pub async fn bgp_create_announce_set(
pub async fn bgp_update_announce_set(
&self,
opctx: &OpContext,
announce: &params::BgpAnnounceSetCreate,
) -> CreateResult<(BgpAnnounceSet, Vec<BgpAnnouncement>)> {
opctx.authorize(authz::Action::Modify, &authz::FLEET).await?;
let result =
self.db_datastore.bgp_create_announce_set(opctx, announce).await?;
self.db_datastore.bgp_update_announce_set(opctx, announce).await?;

// eagerly propagate changes via rpw
self.background_tasks
.activate(&self.background_tasks.task_switch_port_settings_manager);
Ok(result)
}

Expand Down
6 changes: 5 additions & 1 deletion nexus/src/app/switch_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ impl super::Nexus {
)
.await
{
Ok(id) => self.switch_port_settings_update(opctx, id, params).await,
Ok(id) => {
info!(self.log, "updating port settings {id}");
self.switch_port_settings_update(opctx, id, params).await
}
Err(_) => {
info!(self.log, "creating new switch port settings");
self.switch_port_settings_create(opctx, params, None).await
}
}
Expand Down
11 changes: 6 additions & 5 deletions nexus/src/external_api/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ pub(crate) fn external_api() -> NexusApiDescription {
api.register(networking_bgp_status)?;
api.register(networking_bgp_imported_routes_ipv4)?;
api.register(networking_bgp_config_delete)?;
api.register(networking_bgp_announce_set_create)?;
api.register(networking_bgp_announce_set_update)?;
api.register(networking_bgp_announce_set_list)?;
api.register(networking_bgp_announce_set_delete)?;
api.register(networking_bgp_message_history)?;
Expand Down Expand Up @@ -4059,13 +4059,14 @@ async fn networking_bgp_config_delete(
.await
}

/// Create new BGP announce set
/// Update a BGP announce set. If the announce set exists this endpoint replaces
/// the existing announce set with the one specified.
rcgoodfellow marked this conversation as resolved.
Show resolved Hide resolved
#[endpoint {
method = POST,
method = PUT,
path = "/v1/system/networking/bgp-announce",
tags = ["system/networking"],
}]
async fn networking_bgp_announce_set_create(
async fn networking_bgp_announce_set_update(
rqctx: RequestContext<ApiContext>,
config: TypedBody<params::BgpAnnounceSetCreate>,
) -> Result<HttpResponseCreated<BgpAnnounceSet>, HttpError> {
Expand All @@ -4074,7 +4075,7 @@ async fn networking_bgp_announce_set_create(
let nexus = &apictx.context.nexus;
let config = config.into_inner();
let opctx = crate::context::op_context_for_external_api(&rqctx).await?;
let result = nexus.bgp_create_announce_set(&opctx, &config).await?;
let result = nexus.bgp_update_announce_set(&opctx, &config).await?;
Ok(HttpResponseCreated::<BgpAnnounceSet>(result.0.into()))
};
apictx
Expand Down
2 changes: 1 addition & 1 deletion nexus/tests/integration_tests/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2307,7 +2307,7 @@ pub static VERIFY_ENDPOINTS: Lazy<Vec<VerifyEndpoint>> = Lazy::new(|| {
visibility: Visibility::Public,
unprivileged_access: UnprivilegedAccess::None,
allowed_methods: vec![
AllowedMethod::Post(
AllowedMethod::Put(
serde_json::to_value(&*DEMO_BGP_ANNOUNCE).unwrap(),
),
AllowedMethod::GetNonexistent,
Expand Down
2 changes: 1 addition & 1 deletion nexus/tests/output/nexus_tags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ 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_create POST /v1/system/networking/bgp-announce
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_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: 4 additions & 3 deletions openapi/nexus.json
Original file line number Diff line number Diff line change
Expand Up @@ -6630,12 +6630,13 @@
}
}
},
"post": {
"put": {
"tags": [
"system/networking"
],
"summary": "Create new BGP announce set",
"operationId": "networking_bgp_announce_set_create",
"summary": "Update a BGP announce set. If the announce set exists this endpoint replaces",
"description": "the existing announce set with the one specified.",
"operationId": "networking_bgp_announce_set_update",
"requestBody": {
"content": {
"application/json": {
Expand Down
12 changes: 6 additions & 6 deletions package-manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,10 @@ source.repo = "maghemite"
# `tools/maghemite_openapi_version`. Failing to do so will cause a failure when
# building `ddm-admin-client` (which will instruct you to update
# `tools/maghemite_openapi_version`).
source.commit = "6e0a232fd0b443c19f61f94bf02b7695505aa8e3"
source.commit = "8c5806d0bb3ac38efec716e22fe7cdcd424de09c"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image/<commit>/mg-ddm-gz.sha256.txt
source.sha256 = "01b63e4b2b9537b223a417b9283cefb998ae8a3180108b7fbd7710adcf49bbf0"
source.sha256 = "280bd6e5c30d8f1076bac9b8dbbdbc45379e76259aa6319da257192fcbf64a54"
output.type = "tarball"

[package.mg-ddm]
Expand All @@ -579,10 +579,10 @@ source.repo = "maghemite"
# `tools/maghemite_openapi_version`. Failing to do so will cause a failure when
# building `ddm-admin-client` (which will instruct you to update
# `tools/maghemite_openapi_version`).
source.commit = "6e0a232fd0b443c19f61f94bf02b7695505aa8e3"
source.commit = "8c5806d0bb3ac38efec716e22fe7cdcd424de09c"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image/<commit>/mg-ddm.sha256.txt
source.sha256 = "29ac6f5f61795795a2b1026606ac43d48435f1d685d2db2ab097aaaa9c5d6e6c"
source.sha256 = "f15f8bb0e13b1a9372c895775dae96b68ff1cc5e395e6bad4389c2a97957354e"
output.type = "zone"
output.intermediate_only = true

Expand All @@ -594,10 +594,10 @@ source.repo = "maghemite"
# `tools/maghemite_openapi_version`. Failing to do so will cause a failure when
# building `ddm-admin-client` (which will instruct you to update
# `tools/maghemite_openapi_version`).
source.commit = "6e0a232fd0b443c19f61f94bf02b7695505aa8e3"
source.commit = "8c5806d0bb3ac38efec716e22fe7cdcd424de09c"
# The SHA256 digest is automatically posted to:
# https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image/<commit>/mgd.sha256.txt
source.sha256 = "49f5224ea5f5078c11d71098fea29db9aafe9575876825f4e0216d9c64361f55"
source.sha256 = "b0223e0aad4c22bf980da17084caf6704d0428bad1b3e5daf54e7d415ce82d3e"
output.type = "zone"
output.intermediate_only = true

Expand Down
2 changes: 1 addition & 1 deletion tools/maghemite_ddm_openapi_version
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
COMMIT="6e0a232fd0b443c19f61f94bf02b7695505aa8e3"
COMMIT="8c5806d0bb3ac38efec716e22fe7cdcd424de09c"
SHA2="007bfb717ccbc077c0250dee3121aeb0c5bb0d1c16795429a514fa4f8635a5ef"
2 changes: 1 addition & 1 deletion tools/maghemite_mg_openapi_version
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
COMMIT="6e0a232fd0b443c19f61f94bf02b7695505aa8e3"
COMMIT="8c5806d0bb3ac38efec716e22fe7cdcd424de09c"
SHA2="e4b42ab9daad90f0c561a830b62a9d17e294b4d0da0a6d44b4030929b0c37b7e"
4 changes: 2 additions & 2 deletions tools/maghemite_mgd_checksums
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
CIDL_SHA256="49f5224ea5f5078c11d71098fea29db9aafe9575876825f4e0216d9c64361f55"
MGD_LINUX_SHA256="48aa39bb2d68a81be5ad49986d9ebd3cbad64eee0bd6b4556c91b089760265ec"
CIDL_SHA256="b0223e0aad4c22bf980da17084caf6704d0428bad1b3e5daf54e7d415ce82d3e"
MGD_LINUX_SHA256="776f18e9e7fc905d5a2f33d1a1bdd8863ed988bb2965a222217ec06790a3f452"
Loading
Loading