feat/impl_installable_crd_prometheus #170
@ -1,7 +1,15 @@
|
||||
use std::{collections::BTreeMap, process::Command, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use kube::api::{GroupVersionKind, ObjectMeta};
|
||||
use k8s_openapi::api::{
|
||||
authentication::v1::{TokenRequest, TokenRequestSpec},
|
||||
core::v1::{Secret, ServiceAccount},
|
||||
rbac::v1::{ClusterRoleBinding, RoleRef, Subject},
|
||||
};
|
||||
use kube::{
|
||||
Api,
|
||||
api::{GroupVersionKind, ObjectMeta, PostParams},
|
||||
};
|
||||
use log::{debug, info, warn};
|
||||
use serde::Serialize;
|
||||
use tokio::sync::OnceCell;
|
||||
@ -19,12 +27,14 @@ use crate::{
|
||||
crd_alertmanager_config::CRDPrometheus,
|
||||
crd_grafana::{
|
||||
Grafana as GrafanaCRD, GrafanaDashboard, GrafanaDashboardSpec,
|
||||
GrafanaDatasource, GrafanaDatasourceConfig, GrafanaDatasourceSpec, GrafanaSpec,
|
||||
GrafanaDatasource, GrafanaDatasourceConfig, GrafanaDatasourceJsonData,
|
||||
GrafanaDatasourceSecureJsonData, GrafanaDatasourceSpec, GrafanaSpec,
|
||||
},
|
||||
crd_prometheuses::LabelSelector,
|
||||
grafana_default_dashboard::build_default_dashboard,
|
||||
prometheus_operator::prometheus_operator_helm_chart_score,
|
||||
rhob_alertmanager_config::RHOBObservability,
|
||||
role::build_prom_service_account,
|
||||
service_monitor::ServiceMonitor,
|
||||
},
|
||||
},
|
||||
@ -142,8 +152,26 @@ impl Grafana for K8sAnywhereTopology {
|
||||
};
|
||||
|
||||
let client = self.k8s_client().await?;
|
||||
let url = format!("{}:9091", self.get_domain("thanos-querier").await.unwrap());
|
||||
|
||||
let datasource = self.build_grafana_datasource(ns, &label_selector);
|
||||
let sa = self.build_service_account();
|
||||
//TODO finish this section
|
||||
//needs apply Api<Secret> or something
|
||||
client.apply(&sa, Some(ns)).await?;
|
||||
|
||||
let token_request =self.get_token_request();
|
||||
//this wont work needs a new function for apply secret
|
||||
client.apply(&token_request, Some(ns)).await?;
|
||||
|
||||
let clusterrolebinding = self.build_cluster_rolebinding();
|
||||
|
||||
client.apply(&clusterrolebinding, Some(ns)).await?;
|
||||
|
||||
let secret = self.build_token_secret();
|
||||
|
||||
client.apply(&secret, Some(ns)).await?;
|
||||
|
||||
let datasource = self.build_grafana_datasource(ns, &label_selector, &url);
|
||||
|
||||
client.apply(&datasource, Some(ns)).await?;
|
||||
|
||||
@ -334,35 +362,121 @@ impl K8sAnywhereTopology {
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn build_service_account(&self, name: &str, namespace: &str) -> ServiceAccount {
|
||||
build_prom_service_account(name.to_string(), namespace.to_string())
|
||||
}
|
||||
|
||||
pub fn build_cluster_rolebinding(
|
||||
&self,
|
||||
ns: &str,
|
||||
account_name: &str,
|
||||
role: &str,
|
||||
) -> ClusterRoleBinding {
|
||||
ClusterRoleBinding {
|
||||
metadata: ObjectMeta {
|
||||
name: Some(format!("{}-view-binding", account_name)),
|
||||
..Default::default()
|
||||
},
|
||||
role_ref: RoleRef {
|
||||
api_group: "rbac.authorization.k8s.io".into(),
|
||||
kind: "ClusterRole".into(),
|
||||
name: role.into(),
|
||||
},
|
||||
subjects: Some(vec![Subject {
|
||||
kind: "ServiceAccount".into(),
|
||||
name: account_name.into(),
|
||||
namespace: Some(ns.into()),
|
||||
..Default::default()
|
||||
}]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_token_request(&self) -> TokenRequest {
|
||||
TokenRequest {
|
||||
spec: TokenRequestSpec {
|
||||
audiences: vec!["https://kubernetes.default.svc".to_string()],
|
||||
expiration_seconds: Some(3600),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_token_secret(&self, token: &str, ns: &str) -> Secret {
|
||||
Secret {
|
||||
metadata: ObjectMeta {
|
||||
name: Some("grafana-credentials".into()),
|
||||
namespace: Some(ns.into()),
|
||||
..Default::default()
|
||||
},
|
||||
string_data: Some(std::collections::BTreeMap::from([(
|
||||
"PROMETHEUS_TOKEN".into(),
|
||||
format!("Bearer {}", token),
|
||||
)])),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn build_grafana_datasource(
|
||||
&self,
|
||||
ns: &str,
|
||||
label_selector: &LabelSelector,
|
||||
url: &str,
|
||||
) -> GrafanaDatasource {
|
||||
let mut json_data = BTreeMap::new();
|
||||
json_data.insert("timeInterval".to_string(), "5s".to_string());
|
||||
//
|
||||
// let graf_data_source = GrafanaDatasource {
|
||||
// metadata: ObjectMeta {
|
||||
// name: Some(format!("grafana-datasource-{}", ns)),
|
||||
// namespace: Some(ns.to_string()),
|
||||
// ..Default::default()
|
||||
// },
|
||||
// spec: GrafanaDatasourceSpec {
|
||||
// instance_selector: label_selector.clone(),
|
||||
// allow_cross_namespace_import: Some(false),
|
||||
// datasource: GrafanaDatasourceConfig {
|
||||
// access: "proxy".to_string(),
|
||||
// database: Some("prometheus".to_string()),
|
||||
// json_data: Some(json_data),
|
||||
// //this is fragile
|
||||
// name: format!("prometheus-{}-0", ns),
|
||||
// r#type: "prometheus".to_string(),
|
||||
// url: url.to_string(),
|
||||
// //url: format!("http://prometheus-operated.{}.svc.cluster.local:9090", ns),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// graf_data_source
|
||||
|
||||
let graf_data_source = GrafanaDatasource {
|
||||
GrafanaDatasource {
|
||||
metadata: ObjectMeta {
|
||||
name: Some(format!("grafana-datasource-{}", ns)),
|
||||
name: Some("thanos-prometheus".to_string()),
|
||||
namespace: Some(ns.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
spec: GrafanaDatasourceSpec {
|
||||
instance_selector: label_selector.clone(),
|
||||
allow_cross_namespace_import: Some(false),
|
||||
allow_cross_namespace_import: Some(true),
|
||||
datasource: GrafanaDatasourceConfig {
|
||||
access: "proxy".to_string(),
|
||||
database: Some("prometheus".to_string()),
|
||||
json_data: Some(json_data),
|
||||
//this is fragile
|
||||
name: format!("prometheus-{}-0", ns),
|
||||
name: "OpenShift-Thanos".to_string(),
|
||||
r#type: "prometheus".to_string(),
|
||||
url: format!("http://prometheus-operated.{}.svc.cluster.local:9090", ns),
|
||||
url: url.to_string(),
|
||||
database: None,
|
||||
json_data: Some(GrafanaDatasourceJsonData {
|
||||
time_interval: Some("60s".to_string()),
|
||||
http_header_name1: Some("Authorization".to_string()),
|
||||
}),
|
||||
secure_json_data: Some(GrafanaDatasourceSecureJsonData {
|
||||
http_header_value1: Some("Bearer eyJhbGc...".to_string()),
|
||||
}),
|
||||
is_default: Some(false),
|
||||
editable: Some(true),
|
||||
version: Some(1),
|
||||
},
|
||||
},
|
||||
};
|
||||
graf_data_source
|
||||
}
|
||||
}
|
||||
|
||||
fn build_grafana_dashboard(
|
||||
|
@ -133,13 +133,43 @@ pub struct GrafanaDatasourceSpec {
|
||||
pub struct GrafanaDatasourceConfig {
|
||||
pub access: String,
|
||||
pub database: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub json_data: Option<BTreeMap<String, String>>,
|
||||
pub name: String,
|
||||
pub r#type: String,
|
||||
pub url: String,
|
||||
/// Represents jsonData in the GrafanaDatasource spec
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub json_data: Option<GrafanaDatasourceJsonData>,
|
||||
|
||||
/// Represents secureJsonData (secrets)
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub secure_json_data: Option<GrafanaDatasourceSecureJsonData>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub is_default: Option<bool>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub editable: Option<bool>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GrafanaDatasourceJsonData {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub time_interval: Option<String>,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub http_header_name1: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GrafanaDatasourceSecureJsonData {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub http_header_value1: Option<String>,
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, Default)]
|
||||
|
Loading…
Reference in New Issue
Block a user