Skip to content

Conversation

@sbernauer
Copy link
Member

@sbernauer sbernauer commented Oct 15, 2025

Closes #1

New endpoints

/admin/clusters/status
/admin/clusters/{cluster_name}/status
/admin/clusters/{cluster_name}/activate
/admin/clusters/{cluster_name}/deactivate

Tested with and without autoscaling

@sbernauer sbernauer force-pushed the feat/activation-api branch from edf21ee to 4fd0463 Compare October 15, 2025 12:15
@sbernauer sbernauer marked this pull request as ready for review October 16, 2025 07:11
@sbernauer sbernauer self-assigned this Oct 16, 2025
@sbernauer sbernauer moved this to Development: Waiting for Review in Stackable Engineering Oct 16, 2025
@sbernauer sbernauer requested a review from maltesander October 16, 2025 07:30
Comment on lines 125 to 133
.route(
"/admin/activate-cluster/{cluster_name}",
post(admin::post_activate_cluster),
)
.route(
"/admin/deactivate-cluster/{cluster_name}",
post(admin::post_deactivate_cluster),
)
.route("/admin/cluster-status", get(admin::get_cluster_status))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: I think it makes sense to not even add these routes if no admin credentials are configured. This would also remove the need for the NoAdminAuthenticationMethodDefined error variant above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer nice error handling.
Getting a 403 with a helpful error message is way nicer than a 404 and going what the heck.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I guess that is a better user experience.

I just thought checking for if let Some(_) = admin_creds on every handler call is quite cumbersome.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, but

  1. it's only two endpoints
  2. The if let Some() would be needed in any case, as we need to check the username and password. We could do something with middleware and stuff but that sounds like premature optimization

Error::SetClusterStateInPersistence { .. } => StatusCode::INTERNAL_SERVER_ERROR,
Error::GetAllClusterStates { .. } => StatusCode::INTERNAL_SERVER_ERROR,
};
(status_code, format!("{self}")).into_response()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use self.to_string() to avoid unnecessary format! call (because to_string most likely already uses a format! call internally via the Display impl).

Suggested change
(status_code, format!("{self}")).into_response()
(status_code, self.to_string()).into_response()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep it as is for consistency with all the other places.
Long term we should use a different formatter actually

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep it as is for consistency with all the other places.

Sure, but that format! call is literally useless (it even has overhead). I think doing the better thing here trumps consistency.

Long term we should use a different formatter actually

Different formatter? Or do you mean different format? Otherwise I'm confused by this statement and would require a more detailed explanation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I confused this, this only works for anyhow IIRC. You can use some flags so that it prints the error trace separated with colons.
Looks like snafu can't do this, so I added 8cc8f97, WDYT?

Comment on lines 98 to 102
/// Get the status of the Trino clusters
#[instrument(name = "GET /admin/cluster-status", skip(state))]
pub async fn get_cluster_status(
State(state): State<Arc<AppState>>,
) -> Result<Json<BTreeMap<TrinoClusterName, ClusterStats>>, Error> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Does it make sense to also support retrieving the status of a single cluster via GET /admin/cluster-status/{cluster_name}?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a nice addition yes. Do you want me to do this in this PR already?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, if you feel like it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in e43e373.
This also improves the consistency of the HTTP paths

@Techassi Techassi moved this from Development: Waiting for Review to Development: In Review in Stackable Engineering Oct 17, 2025
@sbernauer sbernauer requested a review from Techassi October 20, 2025 06:15
@sbernauer sbernauer force-pushed the feat/activation-api branch from 042689f to 8cc8f97 Compare October 27, 2025 09:55
@sbernauer sbernauer requested review from Techassi and removed request for Techassi October 27, 2025 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development: In Review

Development

Successfully merging this pull request may close these issues.

Allow marking clusters as activated/deactivated via API call

3 participants