Skip to content

Commit

Permalink
grafana init setup
Browse files Browse the repository at this point in the history
  • Loading branch information
“Giems” committed Aug 9, 2024
1 parent ab6af57 commit 5979439
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 34 deletions.
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ ENV=DEV # PROD or DEV
ONLY_RELAY_SERVICE=FALSE # TRUE - This will start only nightly relay service without cloud service
NONCE=VERY_SECRET_NONCE
MAILER_ADDRESS=[email protected]
# Different than db address specified in infra/.env due to docker shenanigans, used in setting up datasource in grafana
# This is a address of the whole docker interface not just container with database
# Can be found by looking for docker0 entry by sing command ifconfig/ip -a
DATABASE_ADDRESS=172.17.0.1
GRAFANA_BASE_PATH=http://localhost:3005/api
# TEST LOGIN DO NO USE IN PRODUCTION
GF_SECURITY_ADMIN_USER=admin
Expand Down
6 changes: 6 additions & 0 deletions server/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct ENV {
pub NONCE: String,
pub MAILER_ADDRESS: String,
pub MAILER_PASSWORD: String,
pub DATABASE_ADDRESS: String,
pub GRAFANA_BASE_PATH: String,
pub GF_SECURITY_ADMIN_USER: String,
pub GF_SECURITY_ADMIN_PASSWORD: String,
Expand All @@ -35,6 +36,8 @@ pub fn get_env() -> &'static ENV {
.expect("Failed to get MAILER_ADDRESS env"),
MAILER_PASSWORD: std::env::var("MAILER_PASSWORD")
.expect("Failed to get MAILER_PASSWORD env"),
DATABASE_ADDRESS: std::env::var("DATABASE_ADDRESS")
.expect("Failed to get DATABASE_ADDRESS env"),
GRAFANA_BASE_PATH: std::env::var("GRAFANA_BASE_PATH")
.expect("Failed to get GRAFANA_BASE_PATH env"),
GF_SECURITY_ADMIN_USER: std::env::var("GF_SECURITY_ADMIN_USER")
Expand Down Expand Up @@ -85,3 +88,6 @@ pub fn GF_SECURITY_ADMIN_PASSWORD() -> &'static str {
pub fn MAILER_ACTIVE() -> bool {
get_env().MAILER_ACTIVE
}
pub fn DATABASE_ADDRESS() -> &'static str {
get_env().DATABASE_ADDRESS.as_str()
}
37 changes: 25 additions & 12 deletions server/src/http/cloud/grafana_utils/import_template_dashboard.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::{
statics::{DASHBOARD_TEMPLATE_UID, TEMPLATES_FOLDER_UID},
statics::{DASHBOARD_TEMPLATE_UID, POSTGRES_DATASOURCE_UID, TEMPLATES_FOLDER_UID},
structs::cloud::grafana_error::handle_grafana_error,
};
use axum::http::StatusCode;
use log::{error, info, warn};
use openapi::{
apis::{
configuration::Configuration,
dashboards_api::{get_dashboard_by_uid, import_dashboard},
},
models::ImportDashboardRequest,
models::{ImportDashboardInput, ImportDashboardRequest},
};
use serde_json::Value;
use std::{env, sync::Arc};
Expand All @@ -34,44 +35,56 @@ pub async fn setup_templates_dashboard(
Ok(response) => match response.dashboard {
Some(_dashboard) => return Ok(()),
None => {
// Try to import the dashboard
warn!("Failed to get dashboard data event though grafana returned 200");

// Try to import the dashboard anyway
let request = ImportDashboardRequest {
dashboard: Some(dashboard),
folder_id: None,
folder_uid: Some(TEMPLATES_FOLDER_UID.to_string()),
overwrite: Some(false),
inputs: None,
overwrite: Some(true),
inputs: Some(vec![ImportDashboardInput {
name: Some("DS_GRAFANA-POSTGRESQL-DATASOURCE".to_string()),
plugin_id: Some("grafana-postgres-datasource".to_string()),
r#type: Some("datasource".to_string()),
value: Some(POSTGRES_DATASOURCE_UID.to_string()),
}]),
path: None,
plugin_id: None,
};

match import_dashboard(&grafana_conf, request).await {
Ok(_) => return Ok(()),
Err(err) => {
println!("Failed to import template dashboard: {:?}", err);
error!("Failed to import template dashboard: {:?}", err);
return Err(handle_grafana_error(err));
}
}
}
},
Err(err) => {
println!("Failed to import template dashboard: {:?}", err);
Err(_) => {
info!("Template dashboard does not exists, creating it");

// Try to import the dashboard anyway
// Try to import the dashboard
let request = ImportDashboardRequest {
dashboard: Some(dashboard),
folder_id: None,
folder_uid: Some(TEMPLATES_FOLDER_UID.to_string()),
overwrite: Some(false),
inputs: None,
overwrite: Some(true),
inputs: Some(vec![ImportDashboardInput {
name: Some("DS_GRAFANA-POSTGRESQL-DATASOURCE".to_string()),
plugin_id: Some("grafana-postgres-datasource".to_string()),
r#type: Some("datasource".to_string()),
value: Some(POSTGRES_DATASOURCE_UID.to_string()),
}]),
path: None,
plugin_id: None,
};

match import_dashboard(&grafana_conf, request).await {
Ok(_) => return Ok(()),
Err(err) => {
println!("Failed to import template dashboard: {:?}", err);
error!("Failed to import template dashboard: {:?}", err);
return Err(handle_grafana_error(err));
}
}
Expand Down
1 change: 1 addition & 0 deletions server/src/http/cloud/grafana_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ pub mod create_new_app;
pub mod create_new_team;
pub mod import_template_dashboard;
pub mod remove_user_from_the_team;
pub mod setup_database_datasource;
pub mod setup_template_folder;
49 changes: 49 additions & 0 deletions server/src/http/cloud/grafana_utils/setup_database_datasource.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::{
env::DATABASE_ADDRESS,
infra_env::{POSTGRES_DB, POSTGRES_USER},
statics::POSTGRES_DATASOURCE_UID,
structs::cloud::grafana_error::handle_grafana_error,
};
use axum::http::StatusCode;
use openapi::{
apis::{
configuration::Configuration,
datasources_api::{add_data_source, get_data_source_by_uid},
},
models::AddDataSourceCommand,
};
use std::sync::Arc;

pub async fn setup_database_datasource(
grafana_conf: &Arc<Configuration>,
) -> Result<(), (StatusCode, String)> {
// Check if datasource already exists, otherwise create it
if let Err(_) = get_data_source_by_uid(grafana_conf, POSTGRES_DATASOURCE_UID).await {
let request_payload = AddDataSourceCommand {
name: Some("Postgres".to_string()),
r#type: Some("postgres".to_string()),
access: Some("proxy".to_string()),
// DATABASE ADDRESS from main env file
url: Some(DATABASE_ADDRESS().to_string()),
database: Some(POSTGRES_DB().to_string()),
user: Some(POSTGRES_USER().to_string()),
basic_auth: None,
with_credentials: Some(false),
is_default: Some(true),
json_data: None,
uid: Some(POSTGRES_DATASOURCE_UID.to_string()),
basic_auth_user: None,
secure_json_data: None,
};

match add_data_source(&grafana_conf, request_payload).await {
Ok(_) => return Ok(()),
Err(err) => {
println!("Failed to import database datasource: {:?}", err);
return Err(handle_grafana_error(err));
}
}
}

Ok(())
}
5 changes: 3 additions & 2 deletions server/src/http/cloud/grafana_utils/setup_template_folder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{statics::TEMPLATES_FOLDER_UID, structs::cloud::grafana_error::handle_grafana_error};
use axum::http::StatusCode;
use log::info;
use openapi::{
apis::{
configuration::Configuration,
Expand Down Expand Up @@ -34,8 +35,8 @@ pub async fn setup_templates_folder(
}
}
},
Err(err) => {
println!("Failed to get templates folder: {:?}", err);
Err(_) => {
info!("Templates folder does not exist, creating it");

// Try to create the folder anyway
let folder_request = CreateFolderCommand {
Expand Down
168 changes: 168 additions & 0 deletions server/src/infra_env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#![allow(non_snake_case)]
use once_cell::sync::OnceCell;

#[derive(Debug)]
pub struct INFRA_ENV {
pub ENVIRONMENT: String,
pub ONLY_DATABASE: bool,
pub DATABASE_ADDRESS: String,
pub DATABASE_PORT: String,
pub POSTGRES_USER: String,
pub POSTGRES_PASSWORD: String,
pub POSTGRES_DB: String,
pub PG_DATA: String,
pub TIMESCALEDB_IMAGE: String,
pub OFELIA_IMAGE: String,
pub TIMESCALEDB_DATA: String,
pub TIMESCALEDB_BACKUPS: String,
pub TIMESCALEDB_LOGS: String,
pub TIMESCALEDB_PGBACKREST_CONFIG: String,
pub OFELIA_LOGS: String,
pub MANUAL_BACKUPS: String,
pub CUSTOM_ENTRYPOINT: String,
pub OFELIA_SMTP_HOST: String,
pub OFELIA_SMTP_PORT: String,
pub OFELIA_SMTP_USER: String,
pub OFELIA_SMTP_PASSWORD: String,
pub OFELIA_EMAIL_FROM: String,
pub OFELIA_EMAIL_TO: String,
}

pub fn get_env() -> &'static INFRA_ENV {
static INSTANCE: OnceCell<INFRA_ENV> = OnceCell::new();

INSTANCE.get_or_init(|| {
dotenvy::from_filename(".env").ok();

let env = INFRA_ENV {
ENVIRONMENT: std::env::var("ENV").unwrap_or_else(|_| "DEV".to_string()), // Default to DEV if not set
ONLY_DATABASE: std::env::var("ONLY_DATABASE")
.unwrap_or_else(|_| "false".to_string())
.eq_ignore_ascii_case("true"),
DATABASE_ADDRESS: std::env::var("DATABASE_ADDRESS")
.expect("Failed to get DATABASE_ADDRESS env"),
DATABASE_PORT: std::env::var("DATABASE_PORT").unwrap_or_else(|_| "5432".to_string()), // Default to 5432 if not set
POSTGRES_USER: std::env::var("POSTGRES_USER").expect("Failed to get POSTGRES_USER env"),
POSTGRES_PASSWORD: std::env::var("POSTGRES_PASSWORD")
.expect("Failed to get POSTGRES_PASSWORD env"),
POSTGRES_DB: std::env::var("POSTGRES_DB").expect("Failed to get POSTGRES_DB env"),
PG_DATA: std::env::var("PG_DATA").expect("Failed to get PG_DATA env"),
TIMESCALEDB_IMAGE: std::env::var("TIMESCALEDB_IMAGE")
.expect("Failed to get TIMESCALEDB_IMAGE env"),
OFELIA_IMAGE: std::env::var("OFELIA_IMAGE").expect("Failed to get OFELIA_IMAGE env"),
TIMESCALEDB_DATA: std::env::var("TIMESCALEDB_DATA")
.expect("Failed to get TIMESCALEDB_DATA env"),
TIMESCALEDB_BACKUPS: std::env::var("TIMESCALEDB_BACKUPS")
.expect("Failed to get TIMESCALEDB_BACKUPS env"),
TIMESCALEDB_LOGS: std::env::var("TIMESCALEDB_LOGS")
.expect("Failed to get TIMESCALEDB_LOGS env"),
TIMESCALEDB_PGBACKREST_CONFIG: std::env::var("TIMESCALEDB_PGBACKREST_CONFIG")
.expect("Failed to get TIMESCALEDB_PGBACKREST_CONFIG env"),
OFELIA_LOGS: std::env::var("OFELIA_LOGS").expect("Failed to get OFELIA_LOGS env"),
MANUAL_BACKUPS: std::env::var("MANUAL_BACKUPS")
.expect("Failed to get MANUAL_BACKUPS env"),
CUSTOM_ENTRYPOINT: std::env::var("CUSTOM_ENTRYPOINT")
.expect("Failed to get CUSTOM_ENTRYPOINT env"),
OFELIA_SMTP_HOST: std::env::var("OFELIA_SMTP_HOST")
.expect("Failed to get OFELIA_SMTP_HOST env"),
OFELIA_SMTP_PORT: std::env::var("OFELIA_SMTP_PORT")
.expect("Failed to get OFELIA_SMTP_PORT env"),
OFELIA_SMTP_USER: std::env::var("OFELIA_SMTP_USER")
.expect("Failed to get OFELIA_SMTP_USER env"),
OFELIA_SMTP_PASSWORD: std::env::var("OFELIA_SMTP_PASSWORD")
.expect("Failed to get OFELIA_SMTP_PASSWORD env"),
OFELIA_EMAIL_FROM: std::env::var("OFELIA_EMAIL_FROM")
.expect("Failed to get OFELIA_EMAIL_FROM env"),
OFELIA_EMAIL_TO: std::env::var("OFELIA_EMAIL_TO")
.expect("Failed to get OFELIA_EMAIL_TO env"),
};
return env;
})
}
pub fn ONLY_DATABASE() -> bool {
get_env().ONLY_DATABASE
}

pub fn DATABASE_ADDRESS() -> &'static str {
get_env().DATABASE_ADDRESS.as_str()
}

pub fn DATABASE_PORT() -> &'static str {
get_env().DATABASE_PORT.as_str()
}

pub fn POSTGRES_USER() -> &'static str {
get_env().POSTGRES_USER.as_str()
}

pub fn POSTGRES_PASSWORD() -> &'static str {
get_env().POSTGRES_PASSWORD.as_str()
}

pub fn POSTGRES_DB() -> &'static str {
get_env().POSTGRES_DB.as_str()
}

pub fn PG_DATA() -> &'static str {
get_env().PG_DATA.as_str()
}

pub fn TIMESCALEDB_IMAGE() -> &'static str {
get_env().TIMESCALEDB_IMAGE.as_str()
}

pub fn OFELIA_IMAGE() -> &'static str {
get_env().OFELIA_IMAGE.as_str()
}

pub fn TIMESCALEDB_DATA() -> &'static str {
get_env().TIMESCALEDB_DATA.as_str()
}

pub fn TIMESCALEDB_BACKUPS() -> &'static str {
get_env().TIMESCALEDB_BACKUPS.as_str()
}

pub fn TIMESCALEDB_LOGS() -> &'static str {
get_env().TIMESCALEDB_LOGS.as_str()
}

pub fn TIMESCALEDB_PGBACKREST_CONFIG() -> &'static str {
get_env().TIMESCALEDB_PGBACKREST_CONFIG.as_str()
}

pub fn OFELIA_LOGS() -> &'static str {
get_env().OFELIA_LOGS.as_str()
}

pub fn MANUAL_BACKUPS() -> &'static str {
get_env().MANUAL_BACKUPS.as_str()
}

pub fn CUSTOM_ENTRYPOINT() -> &'static str {
get_env().CUSTOM_ENTRYPOINT.as_str()
}

pub fn OFELIA_SMTP_HOST() -> &'static str {
get_env().OFELIA_SMTP_HOST.as_str()
}

pub fn OFELIA_SMTP_PORT() -> &'static str {
get_env().OFELIA_SMTP_PORT.as_str()
}

pub fn OFELIA_SMTP_USER() -> &'static str {
get_env().OFELIA_SMTP_USER.as_str()
}

pub fn OFELIA_SMTP_PASSWORD() -> &'static str {
get_env().OFELIA_SMTP_PASSWORD.as_str()
}

pub fn OFELIA_EMAIL_FROM() -> &'static str {
get_env().OFELIA_EMAIL_FROM.as_str()
}

pub fn OFELIA_EMAIL_TO() -> &'static str {
get_env().OFELIA_EMAIL_TO.as_str()
}
1 change: 1 addition & 0 deletions server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod env;
pub mod errors;
pub mod handle_error;
pub mod http;
pub mod infra_env;
pub mod ip_geolocation;
pub mod mailer;
pub mod middlewares;
Expand Down
Loading

0 comments on commit 5979439

Please sign in to comment.