-
Notifications
You must be signed in to change notification settings - Fork 43
[external API] alerts: the renamening #8169
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
base: main
Are you sure you want to change the base?
Conversation
had to go back and un-rename some columns since apparently CRDB can't do that (sad face!)
i gotta stop forgetting expectorate tests
Clone, Debug, Queryable, Selectable, Insertable, Serialize, Deserialize, | ||
)] | ||
#[diesel(table_name = alert_subscription)] | ||
pub struct AlertRxSubscription { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for myself: this was moved from nexus/db-model/src/webhook_rx.rs
Co-authored-by: Sean Klein <sean@oxide.computer>
Co-authored-by: Sean Klein <sean@oxide.computer>
Co-authored-by: Sean Klein <sean@oxide.computer>
@david-crespo re:
Yeah, I agree that this feels a bit weird. One thing I considered doing is also having a |
Oh, @smklein, one other thing: there are a couple of places where we now have tables that have a few columns with unfortunate names ("event_class" and "event_id" rather than "alert_class" and "alert_id") because CRDB doesn't support renaming columns idempotently. Do you think it's worth changing the migrations to drop those tables and create new ones with nicer names, instead of just renaming the table? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
took a pass comparing what we had determined in the CLI with the changes you're proposing to the API
nexus/external-api/src/lib.rs
Outdated
@@ -3660,79 +3693,48 @@ pub trait NexusExternalApi { | |||
/// queued for re-delivery. | |||
#[endpoint { | |||
method = POST, | |||
path = "/v1/webhooks/receivers/{receiver}/probe", | |||
tags = ["system/webhooks"], | |||
path = "/v1/webhook-receivers/{receiver}/probe", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you consider nesting webhook-receivers under alerts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I had initially wanted to do /v1/alert-receivers/webhooks
. however, we can't nest routes under a route which can also look up a resource by name. because there's a /v1/alert-receivers/{name-or-id}
route, we can't also have a /v1/alert-receivers/webhooks/{name-or-id}
route, since it's unclear whether /webhooks
should be treated as a receiver name or as a routable path segment.
i did also consider nesting all of this stuff under a top-level /v1/alerts
, so /v1/alerts/receivers
, /v1/alerts/webhook-receivers
, and so on. however, /v1/alerts
is also the route for looking up the actual alert resource (currently used for resend but maybe also for actually getting the payload etc in future). alerts are only looked up by UUID and never by name, so we could nest other routes under /v1/alerts
, but it felt a bit weird, and i didn't want to put the alert-lookup route under /v1/alerts/alerts
because...that's gross.
also, @david-crespo had previously told me that we try to keep the public API as "flat" as possible rather than nesting, and i think the /v1/alerts
, /v1/alert-receivers
, /v1/alert-deliveries
etc structure is closer to what we've done elsewhere? if either of you have suggestions for a better structure given all that, though, i'm all ears!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@david-crespo can you comment? It seems like "as flat as possible... but not flatter" might be the addendum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I think the middle paragraph is the real constraint, rather than the aesthetic norm about flatness. We don't have anywhere else in the API where we support both /v1/alerts/1f733f7b-b2eb-429c-8b3a-69203cb55cd7
and /v1/alerts/receivers/...
. I think that's worse than what we currently have in this PR. Though overall the difficulty here I think is the same one I was pointing to in #8169 (comment) — the structure doesn't feel quite natural, though I concede that's an initial impression and I am totally open to the idea that a) it's not yet worth the effort required to get it to feel intuitive, since we don't know how the feature will evolve, and b) initial impression is less important than whether it's usable after spending a little time wiht it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also the option of double-nesting, i.e. having /v1/alerts/alerts/1f733f7b-b2eb-429c-8b3a-69203cb55cd7
and /v1/alerts/receivers/my-cool-receiver
, I suppose. But, the "alerts/alerts" feels unpleasant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in my humble opinion, no to alerts/alerts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i really didn't like it either...
#[endpoint { | ||
method = PUT, | ||
path = "/v1/webhooks/receivers/{receiver}", | ||
tags = ["system/webhooks"], | ||
method = POST, | ||
path = "/v1/alert-receivers/{receiver}/subscriptions", | ||
tags = ["system/alerts"], | ||
}] | ||
async fn webhook_receiver_update( | ||
async fn alert_receiver_subscription_add( | ||
rqctx: RequestContext<Self::Context>, | ||
path_params: Path<params::WebhookReceiverSelector>, | ||
params: TypedBody<params::WebhookReceiverUpdate>, | ||
) -> Result<HttpResponseUpdatedNoContent, HttpError>; | ||
path_params: Path<params::AlertReceiverSelector>, | ||
params: TypedBody<params::AlertSubscriptionCreate>, | ||
) -> Result<HttpResponseCreated<views::AlertSubscriptionCreated>, HttpError>; | ||
|
||
/// Delete webhook receiver | ||
/// Remove alert receiver subscription | ||
#[endpoint { | ||
method = DELETE, | ||
path = "/v1/webhooks/receivers/{receiver}", | ||
tags = ["system/webhooks"], | ||
path = "/v1/alert-receivers/{receiver}/subscriptions/{subscription}", | ||
tags = ["system/alerts"], | ||
}] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you made what I thought was a good suggestion in the CLI to call these oxide alert receiver subscribe
and oxide alert receiver unsubscribe
. Do you now prefer subscription add/remove? I think I prefer the former, but my only strong preference is that CLI and API match in this regard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like the "subscribe"/"unsubscribe" naming for the CLI. per this comment from @david-crespo we prefer to use verbs like "add"/"remove" in API routes because they're consistent with other API operations, rather than descriptive verbs like "subscribe"/"unsubscribe". personally i think i would strongly prefer the more descriptive verbs in the CLI and don't have strong preferences about whether we should also use that in the API...perhaps it's more important for both to be consistent with each other than to use the more descriptive verbs, i dunno...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds fine; just wanted to make sure we're making the decision eyes open.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i definitely think there's value in using the same verbs in the CLI and the API, because then the CLI becomes a sort of teaching tool for the API: if you've done something manually, you know exactly where to look if you want to do it programmatically. but, i'm not totally sure how strongly we've weighed that against other concerns in the past. are there any cases where we've intentionally chosen to use different verbs (or nouns!) in the CLI, or are they always the same?
What about creation via
My suggestion is that we do one or the other for now i.e. "list all receivers" (which happen to just be webhooks) or "list webhook receivers" (which happen to be all receivers). In the future, I can't imagine the utility for listing JUST the webhooks, but I have been known to lack imagination!
Given that a second flavor of webhook is speculation at this point, I would suggest just pick something and re-evaluate when we have something more concrete in the future. |
Unfortunately we can't have a route like that, as receivers are looked up by name, and there's an ambiguity as to whether |
9d384ea
to
56399ec
Compare
In conversation with @ahl, we have determined that the external API for webhooks added in #7277 should be changed to focus on "alerts" as the first-class user-facing concept, with "webhooks" as one delivery mechanism for alerts. This way, we can talk about alerts as an entity in the API that exist independently of webhooks that deliver alerts, and the same alert types can be shared with other alert delivery mechanisms if any are added in the future.
What we currently refer to as "webhook events" and "webhook event classes" are therefore renamed to "alerts" and "alert classes". The current concept of "webhook receivers" is generalized to an "alert receiver" resource, of which webhook receivers are (currently) the only subtype. This way, if we add other mechanisms of delivering alerts in the future (email, first-class Slack integration, etc), we can introduce new subtypes of alert receivers. I've restructured the API to have both
/v1/alert-receivers/...
and/v1/webhook-receivers/...
routes, with operations common to all alert receivers (list, view, add/remove subscriptions, delete) under thealert-receivers
route, and operations related to webhook-specific configuration (add/remove secrets, probe, deliveries) under thewebhook-receivers
route. I've also changed theAlertReceiver
view to have a "kind" enum that stores the subtype-specific configuration; currently, this will only ever be "webhook", but I thought it was worth doing this now to make future additions cause less breakage for API consumers.This is, admittedly, a somewhat large diff, but fortunately, most of it is just renaming stuff and moving it around. Reviewers can focus more or less exclusively to the changes to the external API routes and models, and maybe the database migrations. Any mistakes while renaming and moving things around have already been caught by the Rust compiler. :)