init: skeleton for dashboard configuration state

This commit is contained in:
Jeremy Wall 2024-02-03 16:31:41 -06:00
parent e607ce53ea
commit d4b38830e6
5 changed files with 99 additions and 9 deletions

View File

@ -7,13 +7,15 @@ license = "Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.79"
async-io = "2.3.1"
axum = "0.7.4"
axum = { version = "0.7.4", features = [ "ws" ] }
clap = { version = "4.4.18", features = ["derive"] }
maud = { version = "0.26.0", features = ["axum"] }
prometheus-http-api = "0.2.0"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
serde_yaml = "0.9.31"
smol = "2.0.0"
smol-axum = "0.1.0"
smol-macros = "0.1.0"

34
src/dashboard.rs Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2021 Jeremy Wall
//
// 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 std::path::Path;
use serde::Deserialize;
use serde_yaml;
#[derive(Deserialize)]
pub struct Dashboard {
title: String,
graphs: Vec<Graph>,
}
#[derive(Deserialize)]
pub struct Graph {
title: String,
query: String,
}
pub fn read_dashboard_list(path: &Path) -> anyhow::Result<Vec<Dashboard>> {
let f = std::fs::File::open(path)?;
Ok(serde_yaml::from_reader(f)?)
}

View File

@ -11,15 +11,18 @@
// 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 std::io;
use std::net::TcpListener;
use std::path::PathBuf;
use std::sync::Arc;
use anyhow;
use async_io::Async;
use axum::{self, routing::*, Router};
use clap::{self, Parser};
use smol_macros::main;
mod dashboard;
mod query;
mod routes;
#[derive(clap::Parser)]
@ -27,20 +30,25 @@ mod routes;
struct Cli {
#[arg(long)]
listen: Option<std::net::SocketAddr>,
#[arg(long)]
config: PathBuf,
}
main! {
async fn main(ex: &Arc<smol_macros::Executor<'_>>) -> io::Result<()> {
async fn main(ex: &Arc<smol_macros::Executor<'_>>) -> anyhow::Result<()> {
let args = Cli::parse();
let config = std::sync::Arc::new(dashboard::read_dashboard_list(args.config.as_path())?);
let router = Router::new()
.with_state(config)
// JSON api endpoints
.nest("/api", routes::mk_api_routes())
// HTMX ui component endpoints
.nest("/ui", routes::mk_ui_routes())
.route("/", get(routes::index));
let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".parse().unwrap());
let socket_addr = args.listen.unwrap_or("127.0.0.1:3000".parse()?);
// TODO(jwall): Take this from clap arguments
let listener = Async::<TcpListener>::bind(socket_addr).unwrap();
smol_axum::serve(ex.clone(), listener, router).await
let listener = Async::<TcpListener>::bind(socket_addr)?;
smol_axum::serve(ex.clone(), listener, router).await?;
Ok(())
}
}

28
src/query.rs Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2021 Jeremy Wall
//
// 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 prometheus_http_api::{DataSource, Query};
pub struct QueryConn {
source: DataSource,
query: Query,
}
impl QueryConn {
pub fn new<S: Into<DataSource>, Q: Into<Query>>(src: S, qry: Q) -> Self {
Self {
source: src.into(),
query: qry.into(),
}
}
}

View File

@ -11,10 +11,17 @@
// 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 std::sync::Arc;
use maud::{html, Markup};
use axum::Router;
use axum::{extract::State, Router};
use crate::dashboard::Dashboard;
type Config = State<Arc<Vec<Dashboard>>>;
pub fn mk_api_routes() -> Router {
// Query routes
Router::new()
}
@ -22,15 +29,26 @@ pub fn mk_ui_routes() -> Router {
Router::new()
}
pub async fn index() -> Markup {
pub async fn index(State(config): Config) -> Markup {
html! {
html {
head {
title { ("Heracles - Prometheus Unshackled") }
}
body {
("hello world")
(app(State(config.clone())).await)
}
}
}
}
pub async fn app(State(config): Config) -> Markup {
html! {
div {
// Header menu
div { }
// dashboard display
div { }
}
}
}