mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2025-12-22 22:20:02 +00:00
feat: embed dashboard into GreptimeDB binary (#1239)
* feat: embed dashboard into GreptimeDB binary * fix: resolve PR comments
This commit is contained in:
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -6076,6 +6076,40 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "6.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb133b9a38b5543fad3807fb2028ea47c5f2b566f4f5e28a11902f1a358348b6"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "6.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "7.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731"
|
||||
dependencies = [
|
||||
"sha2",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.18.0"
|
||||
@@ -6918,6 +6952,7 @@ dependencies = [
|
||||
"hyper",
|
||||
"influxdb_line_protocol",
|
||||
"metrics",
|
||||
"mime_guess",
|
||||
"mysql_async",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
@@ -6932,6 +6967,7 @@ dependencies = [
|
||||
"query",
|
||||
"rand",
|
||||
"regex",
|
||||
"rust-embed",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"schemars",
|
||||
|
||||
39
scripts/fetch-dashboard-assets.sh
Executable file
39
scripts/fetch-dashboard-assets.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script is used to download built dashboard assets from the "GreptimeTeam/dashboard" repository.
|
||||
|
||||
set -e
|
||||
|
||||
declare -r SCRIPT_DIR=$(cd $(dirname ${0}) >/dev/null 2>&1 && pwd)
|
||||
declare -r ROOT_DIR=$(dirname ${SCRIPT_DIR})
|
||||
declare -r STATIC_DIR="$ROOT_DIR/src/servers/dashboard"
|
||||
|
||||
RELEASE_VERSION="$(cat $STATIC_DIR/VERSION)"
|
||||
|
||||
# Download the SHA256 checksum attached to the release. To verify the integrity
|
||||
# of the download, this checksum will be used to check the download tar file
|
||||
# containing the built dashboard assets.
|
||||
curl -Ls https://github.com/GreptimeTeam/dashboard/releases/download/$RELEASE_VERSION/sha256.txt --output sha256.txt
|
||||
|
||||
# Download the tar file containing the built dashboard assets.
|
||||
curl -L https://github.com/GreptimeTeam/dashboard/releases/download/$RELEASE_VERSION/build.tar.gz --output build.tar.gz
|
||||
|
||||
# Verify the checksums match; exit if they don't.
|
||||
case "$(uname -s)" in
|
||||
FreeBSD | Darwin)
|
||||
echo "$(cat sha256.txt)" | shasum --algorithm 256 --check \
|
||||
|| { echo "Checksums did not match for downloaded dashboard assets!"; exit 1; } ;;
|
||||
Linux)
|
||||
echo "$(cat sha256.txt)" | sha256sum --check -- \
|
||||
|| { echo "Checksums did not match for downloaded dashboard assets!"; exit 1; } ;;
|
||||
*)
|
||||
echo "The '$(uname -s)' operating system is not supported as a build host for the dashboard" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# Extract the assets and clean up.
|
||||
tar -xzf build.tar.gz -C "$STATIC_DIR"
|
||||
rm sha256.txt
|
||||
rm build.tar.gz
|
||||
|
||||
echo "Successfully download dashboard assets to $STATIC_DIR"
|
||||
@@ -6,6 +6,7 @@ license.workspace = true
|
||||
|
||||
[features]
|
||||
mem-prof = ["dep:common-mem-prof"]
|
||||
dashboard = []
|
||||
|
||||
[dependencies]
|
||||
aide = { version = "0.9", features = ["axum"] }
|
||||
@@ -39,6 +40,7 @@ humantime-serde = "1.1"
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
influxdb_line_protocol = { git = "https://github.com/evenyag/influxdb_iox", branch = "feat/line-protocol" }
|
||||
metrics = "0.20"
|
||||
mime_guess = "2.0"
|
||||
num_cpus = "1.13"
|
||||
once_cell = "1.16"
|
||||
openmetrics-parser = "0.4"
|
||||
@@ -54,6 +56,7 @@ rand.workspace = true
|
||||
regex = "1.6"
|
||||
rustls = "0.20"
|
||||
rustls-pemfile = "1.0"
|
||||
rust-embed = { version = "6.6", features = ["debug-embed"] }
|
||||
schemars = "0.8"
|
||||
serde.workspace = true
|
||||
serde_json = "1.0"
|
||||
|
||||
54
src/servers/build.rs
Normal file
54
src/servers/build.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
fn main() {
|
||||
#[cfg(feature = "dashboard")]
|
||||
fetch_dashboard_assets();
|
||||
}
|
||||
|
||||
#[cfg(feature = "dashboard")]
|
||||
fn fetch_dashboard_assets() {
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
macro_rules! p {
|
||||
($($tokens: tt)*) => {
|
||||
println!("cargo:warning={}", format!($($tokens)*))
|
||||
}
|
||||
}
|
||||
|
||||
let output = Command::new("./fetch-dashboard-assets.sh")
|
||||
.current_dir("../../scripts")
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.and_then(|p| p.wait_with_output());
|
||||
match output {
|
||||
Ok(output) => {
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
.lines()
|
||||
.for_each(|x| p!("{}", x));
|
||||
|
||||
assert!(output.status.success());
|
||||
}
|
||||
Err(e) => {
|
||||
let e = format!(
|
||||
r#"
|
||||
Failed to fetch dashboard assets: {}.
|
||||
You can manually execute './scripts/fetch-dashboard-assets.sh' to see why,
|
||||
or it's a network error, just try again or enable/disable some proxy."#,
|
||||
e
|
||||
);
|
||||
panic!("{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/servers/dashboard/VERSION
Normal file
1
src/servers/dashboard/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
v0.0.1-test
|
||||
@@ -18,7 +18,7 @@ use std::string::FromUtf8Error;
|
||||
|
||||
use axum::http::StatusCode as HttpStatusCode;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::Json;
|
||||
use axum::{http, Json};
|
||||
use base64::DecodeError;
|
||||
use catalog;
|
||||
use common_error::prelude::*;
|
||||
@@ -275,6 +275,12 @@ pub enum Error {
|
||||
source: tonic_reflection::server::Error,
|
||||
backtrace: Backtrace,
|
||||
},
|
||||
|
||||
#[snafu(display("Failed to build HTTP response, source: {source}"))]
|
||||
BuildHttpResponse {
|
||||
source: http::Error,
|
||||
backtrace: Backtrace,
|
||||
},
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -294,7 +300,8 @@ impl ErrorExt for Error {
|
||||
| TcpBind { .. }
|
||||
| CatalogError { .. }
|
||||
| GrpcReflectionService { .. }
|
||||
| BuildingContext { .. } => StatusCode::Internal,
|
||||
| BuildingContext { .. }
|
||||
| BuildHttpResponse { .. } => StatusCode::Internal,
|
||||
|
||||
InsertScript { source, .. }
|
||||
| ExecuteScript { source, .. }
|
||||
|
||||
@@ -20,6 +20,8 @@ pub mod prometheus;
|
||||
pub mod script;
|
||||
|
||||
mod admin;
|
||||
#[cfg(feature = "dashboard")]
|
||||
mod dashboard;
|
||||
#[cfg(feature = "mem-prof")]
|
||||
pub mod mem_prof;
|
||||
|
||||
@@ -477,6 +479,11 @@ impl HttpServer {
|
||||
routing::get(handler::health).post(handler::health),
|
||||
);
|
||||
|
||||
#[cfg(feature = "dashboard")]
|
||||
{
|
||||
router = router.nest("/dashboard", dashboard::dashboard());
|
||||
}
|
||||
|
||||
router
|
||||
// middlewares
|
||||
.layer(
|
||||
|
||||
56
src/servers/src/http/dashboard.rs
Normal file
56
src/servers/src/http/dashboard.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2023 Greptime Team
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use axum::body::{boxed, Full};
|
||||
use axum::http::{header, StatusCode, Uri};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::Router;
|
||||
use common_telemetry::debug;
|
||||
use rust_embed::RustEmbed;
|
||||
use snafu::ResultExt;
|
||||
|
||||
use crate::error::{BuildHttpResponseSnafu, Result};
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "dashboard/"]
|
||||
pub struct Assets;
|
||||
|
||||
pub(crate) fn dashboard() -> Router {
|
||||
Router::new().fallback(static_handler)
|
||||
}
|
||||
|
||||
#[axum_macros::debug_handler]
|
||||
async fn static_handler(uri: Uri) -> Result<impl IntoResponse> {
|
||||
debug!("[dashboard] requesting: {}", uri.path());
|
||||
|
||||
let mut path = uri.path().trim_start_matches('/');
|
||||
if path.is_empty() {
|
||||
path = "index.html";
|
||||
}
|
||||
|
||||
match Assets::get(path) {
|
||||
Some(content) => {
|
||||
let body = boxed(Full::from(content.data));
|
||||
let mime = mime_guess::from_path(path).first_or_octet_stream();
|
||||
|
||||
Response::builder()
|
||||
.header(header::CONTENT_TYPE, mime.as_ref())
|
||||
.body(body)
|
||||
}
|
||||
None => Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(boxed(Full::from("404"))),
|
||||
}
|
||||
.context(BuildHttpResponseSnafu)
|
||||
}
|
||||
Reference in New Issue
Block a user