-
Notifications
You must be signed in to change notification settings - Fork 39
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
Split clickhouse admin server #6837
Changes from all commits
f039746
ae6337d
2ab43be
9862199
d6dd885
9bf4e03
547dbde
c0531d6
0a2e28b
9adb7f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,56 +2,40 @@ | |
// 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 clickhouse_admin_types::config::{KeeperConfig, ReplicaConfig}; | ||
use clickhouse_admin_types::{ | ||
ClickhouseKeeperClusterMembership, KeeperConf, KeeperSettings, Lgif, | ||
RaftConfig, ServerSettings, | ||
ClickhouseKeeperClusterMembership, KeeperConf, KeeperConfig, | ||
KeeperConfigurableSettings, Lgif, RaftConfig, ReplicaConfig, | ||
ServerConfigurableSettings, | ||
}; | ||
use dropshot::{ | ||
HttpError, HttpResponseCreated, HttpResponseOk, RequestContext, TypedBody, | ||
}; | ||
use omicron_common::api::external::Generation; | ||
use schemars::JsonSchema; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Debug, Serialize, Deserialize, JsonSchema)] | ||
pub struct ServerConfigurableSettings { | ||
/// A unique identifier for the configuration generation. | ||
pub generation: Generation, | ||
/// Configurable settings for a ClickHouse replica server node. | ||
pub settings: ServerSettings, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize, JsonSchema)] | ||
pub struct KeeperConfigurableSettings { | ||
/// A unique identifier for the configuration generation. | ||
pub generation: Generation, | ||
/// Configurable settings for a ClickHouse keeper node. | ||
pub settings: KeeperSettings, | ||
} | ||
|
||
/// API interface for our clickhouse-admin-keeper server | ||
/// | ||
/// We separate the admin interface for the keeper and server APIs because they | ||
/// are completely disjoint. We only run a clickhouse keeper *or* clickhouse | ||
/// server in a given zone, and therefore each admin api is only useful in one | ||
/// of the zones. Using separate APIs and clients prevents us from having to | ||
/// mark a given endpoint `unimplemented` in the case of it not being usable | ||
/// with one of the zone types. | ||
/// | ||
/// Nonetheless, the interfaces themselves are small and serve a similar | ||
/// purpose. Therfore we combine them into the same crate. | ||
#[dropshot::api_description] | ||
pub trait ClickhouseAdminApi { | ||
pub trait ClickhouseAdminKeeperApi { | ||
type Context; | ||
|
||
/// Generate a ClickHouse configuration file for a server node on a specified | ||
/// directory and enable the SMF service. | ||
#[endpoint { | ||
method = PUT, | ||
path = "/server/config-and-enable", | ||
}] | ||
async fn generate_server_config_and_enable( | ||
rqctx: RequestContext<Self::Context>, | ||
body: TypedBody<ServerConfigurableSettings>, | ||
) -> Result<HttpResponseCreated<ReplicaConfig>, HttpError>; | ||
|
||
/// Generate a ClickHouse configuration file for a keeper node on a specified | ||
/// directory and enable the SMF service. | ||
/// directory and enable the SMF service if not currently enabled. | ||
/// | ||
/// Note that we cannot start the keeper service until there is an initial | ||
/// configuration set via this endpoint. | ||
#[endpoint { | ||
method = PUT, | ||
path = "/keeper/config-and-enable", | ||
path = "/config", | ||
}] | ||
async fn generate_keeper_config_and_enable( | ||
async fn generate_config( | ||
rqctx: RequestContext<Self::Context>, | ||
body: TypedBody<KeeperConfigurableSettings>, | ||
) -> Result<HttpResponseCreated<KeeperConfig>, HttpError>; | ||
|
@@ -95,3 +79,30 @@ pub trait ClickhouseAdminApi { | |
rqctx: RequestContext<Self::Context>, | ||
) -> Result<HttpResponseOk<ClickhouseKeeperClusterMembership>, HttpError>; | ||
} | ||
|
||
/// API interface for our clickhouse-admin-server server | ||
/// | ||
/// We separate the admin interface for the keeper and server APIs because they | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 0a2e28b |
||
/// are completely disjoint. We only run a clickhouse keeper *or* clickhouse | ||
/// server in a given zone, and therefore each admin api is only useful in one | ||
/// of the zones. Using separate APIs and clients prevents us from having to | ||
/// mark a given endpoint `unimplemented` in the case of it not being usable | ||
/// with one of the zone types. | ||
/// | ||
/// Nonetheless, the interfaces themselves are small and serve a similar | ||
/// purpose. Therfore we combine them into the same crate. | ||
#[dropshot::api_description] | ||
andrewjstone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub trait ClickhouseAdminServerApi { | ||
type Context; | ||
|
||
/// Generate a ClickHouse configuration file for a server node on a specified | ||
/// directory and enable the SMF service. | ||
#[endpoint { | ||
method = PUT, | ||
path = "/config" | ||
}] | ||
async fn generate_config( | ||
rqctx: RequestContext<Self::Context>, | ||
body: TypedBody<ServerConfigurableSettings>, | ||
) -> Result<HttpResponseCreated<ReplicaConfig>, HttpError>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// 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/. | ||
|
||
//! Executable program to run the Omicron ClickHouse admin interface for | ||
//! clickhouse servers. | ||
|
||
use anyhow::anyhow; | ||
use camino::Utf8PathBuf; | ||
use clap::Parser; | ||
use omicron_clickhouse_admin::{ClickhouseCli, Clickward, Config}; | ||
use omicron_common::cmd::fatal; | ||
use omicron_common::cmd::CmdError; | ||
use std::net::{SocketAddr, SocketAddrV6}; | ||
|
||
#[derive(Debug, Parser)] | ||
#[clap( | ||
name = "clickhouse-admin-server", | ||
about = "Omicron ClickHouse cluster admin server for replica servers" | ||
)] | ||
enum Args { | ||
/// Start the ClickHouse admin server | ||
Run { | ||
/// Address on which this server should run | ||
#[clap(long, short = 'a', action)] | ||
http_address: SocketAddrV6, | ||
|
||
/// Path to the server configuration file | ||
#[clap(long, short, action)] | ||
config: Utf8PathBuf, | ||
|
||
/// Address on which the clickhouse server or keeper is listening on | ||
#[clap(long, short = 'l', action)] | ||
listen_address: SocketAddrV6, | ||
|
||
/// Path to the clickhouse binary | ||
#[clap(long, short, action)] | ||
binary_path: Utf8PathBuf, | ||
}, | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
if let Err(err) = main_impl().await { | ||
fatal(err); | ||
} | ||
} | ||
|
||
async fn main_impl() -> Result<(), CmdError> { | ||
let args = Args::parse(); | ||
|
||
match args { | ||
Args::Run { http_address, config, listen_address, binary_path } => { | ||
let mut config = Config::from_file(&config) | ||
.map_err(|err| CmdError::Failure(anyhow!(err)))?; | ||
config.dropshot.bind_address = SocketAddr::V6(http_address); | ||
let clickward = Clickward::new(); | ||
let clickhouse_cli = | ||
ClickhouseCli::new(binary_path, listen_address); | ||
|
||
let server = omicron_clickhouse_admin::start_server_admin_server( | ||
clickward, | ||
clickhouse_cli, | ||
config, | ||
) | ||
.await | ||
.map_err(|err| CmdError::Failure(anyhow!(err)))?; | ||
server.await.map_err(|err| { | ||
CmdError::Failure(anyhow!( | ||
"server failed after starting: {err}" | ||
)) | ||
}) | ||
} | ||
} | ||
} |
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.
First paragraph of doc comments should be short (a lint for this is coming in Rust 1.83.) Could you just add something simple?
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.
Thanks for the tip! Done in 0a2e28b