wip: fixed token expiration and configured grafana dashboard
This commit is contained in:
parent
06a0c44c3c
commit
7dff70edcf
@ -6,7 +6,9 @@ use std::{
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use k8s_openapi::api::{
|
use k8s_openapi::api::{
|
||||||
authentication::v1::{TokenRequest, TokenRequestSpec, TokenRequestStatus},
|
authentication::v1::{
|
||||||
|
BoundObjectReference, TokenRequest, TokenRequestSpec, TokenRequestStatus,
|
||||||
|
},
|
||||||
core::v1::{Secret, ServiceAccount},
|
core::v1::{Secret, ServiceAccount},
|
||||||
rbac::v1::{ClusterRoleBinding, RoleRef, Subject},
|
rbac::v1::{ClusterRoleBinding, RoleRef, Subject},
|
||||||
};
|
};
|
||||||
@ -30,9 +32,11 @@ use crate::{
|
|||||||
kube_prometheus::crd::{
|
kube_prometheus::crd::{
|
||||||
crd_alertmanager_config::CRDPrometheus,
|
crd_alertmanager_config::CRDPrometheus,
|
||||||
crd_grafana::{
|
crd_grafana::{
|
||||||
Grafana as GrafanaCRD, GrafanaDashboard, GrafanaDashboardSpec,
|
Grafana as GrafanaCRD, GrafanaCom, GrafanaDashboard,
|
||||||
GrafanaDatasource, GrafanaDatasourceConfig, GrafanaDatasourceJsonData,
|
GrafanaDashboardDatasource, GrafanaDashboardSpec, GrafanaDatasource,
|
||||||
GrafanaDatasourceSecureJsonData, GrafanaDatasourceSpec, GrafanaSpec,
|
GrafanaDatasourceConfig, GrafanaDatasourceJsonData,
|
||||||
|
GrafanaDatasourceSecureJsonData, GrafanaDatasourceSpec, GrafanaSecretKeyRef,
|
||||||
|
GrafanaSpec, GrafanaValueFrom, GrafanaValueSource,
|
||||||
},
|
},
|
||||||
crd_prometheuses::LabelSelector,
|
crd_prometheuses::LabelSelector,
|
||||||
grafana_default_dashboard::build_default_dashboard,
|
grafana_default_dashboard::build_default_dashboard,
|
||||||
@ -166,22 +170,24 @@ impl Grafana for K8sAnywhereTopology {
|
|||||||
.wait_until_deployment_ready(
|
.wait_until_deployment_ready(
|
||||||
"grafana-grafana-deployment".to_string(),
|
"grafana-grafana-deployment".to_string(),
|
||||||
Some("grafana"),
|
Some("grafana"),
|
||||||
Some(15),
|
Some(30),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let sa_name = "grafana-grafana-sa";
|
let sa_name = "grafana-grafana-sa";
|
||||||
|
|
||||||
debug!("creating token for sevice account {sa_name}");
|
let token_secret_name = "grafana-sa-token-secret";
|
||||||
let token = self.create_service_account_token(sa_name, ns).await?;
|
|
||||||
|
|
||||||
debug!("creating secret");
|
// let sa_token_secret = self.build_sa_token_secret(token_secret_name, sa_name, ns);
|
||||||
let secret_name = "grafana-sa-secret";
|
//
|
||||||
let secret = self.build_token_secret(secret_name, &token.token, ns).await;
|
// client.apply(&sa_token_secret, Some(ns)).await?;
|
||||||
|
|
||||||
|
let secret = self.build_token_secret(token_secret_name, ns).await;
|
||||||
client.apply(&secret, Some(ns)).await?;
|
client.apply(&secret, Some(ns)).await?;
|
||||||
|
let token_request_status = self.create_service_account_token(sa_name, ns).await?;
|
||||||
|
|
||||||
debug!("creating grafana clusterrole binding");
|
debug!("creating grafana clusterrole binding");
|
||||||
|
|
||||||
let clusterrolebinding =
|
let clusterrolebinding =
|
||||||
self.build_cluster_rolebinding(sa_name, "cluster-monitoring-view", ns);
|
self.build_cluster_rolebinding(sa_name, "cluster-monitoring-view", ns);
|
||||||
|
|
||||||
@ -189,7 +195,7 @@ impl Grafana for K8sAnywhereTopology {
|
|||||||
|
|
||||||
debug!("creating grafana datasource crd");
|
debug!("creating grafana datasource crd");
|
||||||
|
|
||||||
let token_str = format!("Bearer {}", token.token);
|
// let token_str = format!("Bearer {}", token.token);
|
||||||
|
|
||||||
let thanos_url = format!(
|
let thanos_url = format!(
|
||||||
"https://{}",
|
"https://{}",
|
||||||
@ -203,36 +209,11 @@ impl Grafana for K8sAnywhereTopology {
|
|||||||
ns,
|
ns,
|
||||||
&label_selector,
|
&label_selector,
|
||||||
&thanos_url,
|
&thanos_url,
|
||||||
token_str.clone(),
|
&token_request_status.token, // Pass the secret name here
|
||||||
);
|
);
|
||||||
|
|
||||||
client.apply(&thanos_openshift_datasource, Some(ns)).await?;
|
client.apply(&thanos_openshift_datasource, Some(ns)).await?;
|
||||||
|
|
||||||
//TODO user workload datasource returns 503 -> need to figure out how to correctly add the
|
|
||||||
//userworkload thanos-ruler or prometheus-federate to the grafana datasource
|
|
||||||
//it may alrady be included in the overall monitoring stack
|
|
||||||
|
|
||||||
let user_thanos_url = format!(
|
|
||||||
"https://{}",
|
|
||||||
self.get_domain(
|
|
||||||
"thanos-ruler-openshift-user-workload-monitoring.apps.ncd0.harmony.mcd"
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
let thanos_openshift_userworkload_datasource = self.build_grafana_datasource(
|
|
||||||
"thanos-openshift-userworkload-monitoring",
|
|
||||||
ns,
|
|
||||||
&label_selector,
|
|
||||||
&user_thanos_url,
|
|
||||||
token_str.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
client
|
|
||||||
.apply(&thanos_openshift_userworkload_datasource, Some(ns))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
debug!("creating grafana dashboard crd");
|
debug!("creating grafana dashboard crd");
|
||||||
let dashboard = self.build_grafana_dashboard(ns, &label_selector);
|
let dashboard = self.build_grafana_dashboard(ns, &label_selector);
|
||||||
|
|
||||||
@ -446,6 +427,30 @@ impl K8sAnywhereTopology {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_sa_token_secret(
|
||||||
|
&self,
|
||||||
|
secret_name: &str,
|
||||||
|
service_account_name: &str,
|
||||||
|
ns: &str,
|
||||||
|
) -> Secret {
|
||||||
|
let mut annotations = BTreeMap::new();
|
||||||
|
annotations.insert(
|
||||||
|
"kubernetes.io/service-account.name".to_string(),
|
||||||
|
service_account_name.to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Secret {
|
||||||
|
metadata: ObjectMeta {
|
||||||
|
name: Some(secret_name.into()),
|
||||||
|
namespace: Some(ns.into()),
|
||||||
|
annotations: Some(annotations),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
type_: Some("kubernetes.io/service-account-token".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_token_request(&self, ns: &str) -> TokenRequest {
|
pub fn get_token_request(&self, ns: &str) -> TokenRequest {
|
||||||
debug!("building token request");
|
debug!("building token request");
|
||||||
TokenRequest {
|
TokenRequest {
|
||||||
@ -456,7 +461,11 @@ impl K8sAnywhereTopology {
|
|||||||
spec: TokenRequestSpec {
|
spec: TokenRequestSpec {
|
||||||
audiences: vec!["https://kubernetes.default.svc".to_string()],
|
audiences: vec!["https://kubernetes.default.svc".to_string()],
|
||||||
expiration_seconds: Some(3600),
|
expiration_seconds: Some(3600),
|
||||||
..Default::default()
|
bound_object_ref: Some(BoundObjectReference {
|
||||||
|
kind: Some("Secret".to_string()),
|
||||||
|
name: Some("grafana-sa-token-secret".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
@ -486,17 +495,14 @@ impl K8sAnywhereTopology {
|
|||||||
Ok(status)
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn build_token_secret(&self, secret_name: &str, token: &str, ns: &str) -> Secret {
|
pub async fn build_token_secret(&self, secret_name: &str, ns: &str) -> Secret {
|
||||||
Secret {
|
Secret {
|
||||||
metadata: ObjectMeta {
|
metadata: ObjectMeta {
|
||||||
name: Some(secret_name.into()),
|
name: Some(secret_name.into()),
|
||||||
namespace: Some(ns.into()),
|
namespace: Some(ns.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
string_data: Some(std::collections::BTreeMap::from([(
|
string_data: None,
|
||||||
secret_name.into(),
|
|
||||||
format!("Bearer {}", token),
|
|
||||||
)])),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,7 +513,7 @@ impl K8sAnywhereTopology {
|
|||||||
ns: &str,
|
ns: &str,
|
||||||
label_selector: &LabelSelector,
|
label_selector: &LabelSelector,
|
||||||
url: &str,
|
url: &str,
|
||||||
token: String,
|
token: &str, // Pass in the secret name
|
||||||
) -> GrafanaDatasource {
|
) -> GrafanaDatasource {
|
||||||
let mut json_data = BTreeMap::new();
|
let mut json_data = BTreeMap::new();
|
||||||
json_data.insert("timeInterval".to_string(), "5s".to_string());
|
json_data.insert("timeInterval".to_string(), "5s".to_string());
|
||||||
@ -521,6 +527,7 @@ impl K8sAnywhereTopology {
|
|||||||
spec: GrafanaDatasourceSpec {
|
spec: GrafanaDatasourceSpec {
|
||||||
instance_selector: label_selector.clone(),
|
instance_selector: label_selector.clone(),
|
||||||
allow_cross_namespace_import: Some(true),
|
allow_cross_namespace_import: Some(true),
|
||||||
|
values_from: None,
|
||||||
datasource: GrafanaDatasourceConfig {
|
datasource: GrafanaDatasourceConfig {
|
||||||
access: "proxy".to_string(),
|
access: "proxy".to_string(),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
@ -534,7 +541,7 @@ impl K8sAnywhereTopology {
|
|||||||
oauth_pass_thru: Some(true),
|
oauth_pass_thru: Some(true),
|
||||||
}),
|
}),
|
||||||
secure_json_data: Some(GrafanaDatasourceSecureJsonData {
|
secure_json_data: Some(GrafanaDatasourceSecureJsonData {
|
||||||
http_header_value1: Some(token),
|
http_header_value1: Some(format!("Bearer {token}")),
|
||||||
}),
|
}),
|
||||||
is_default: Some(false),
|
is_default: Some(false),
|
||||||
editable: Some(true),
|
editable: Some(true),
|
||||||
@ -548,7 +555,6 @@ impl K8sAnywhereTopology {
|
|||||||
ns: &str,
|
ns: &str,
|
||||||
label_selector: &LabelSelector,
|
label_selector: &LabelSelector,
|
||||||
) -> GrafanaDashboard {
|
) -> GrafanaDashboard {
|
||||||
let json = build_default_dashboard(ns);
|
|
||||||
let graf_dashboard = GrafanaDashboard {
|
let graf_dashboard = GrafanaDashboard {
|
||||||
metadata: ObjectMeta {
|
metadata: ObjectMeta {
|
||||||
name: Some(format!("grafana-dashboard-{}", ns)),
|
name: Some(format!("grafana-dashboard-{}", ns)),
|
||||||
@ -558,7 +564,15 @@ impl K8sAnywhereTopology {
|
|||||||
spec: GrafanaDashboardSpec {
|
spec: GrafanaDashboardSpec {
|
||||||
resync_period: Some("30s".to_string()),
|
resync_period: Some("30s".to_string()),
|
||||||
instance_selector: label_selector.clone(),
|
instance_selector: label_selector.clone(),
|
||||||
json,
|
datasources: Some(vec![GrafanaDashboardDatasource {
|
||||||
|
input_name: "DS_PROMETHEUS".to_string(),
|
||||||
|
datasource_name: "thanos-openshift-monitoring".to_string(),
|
||||||
|
}]),
|
||||||
|
json: None,
|
||||||
|
grafana_com: Some(GrafanaCom {
|
||||||
|
id: 17406,
|
||||||
|
revision: None,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
graf_dashboard
|
graf_dashboard
|
||||||
|
@ -103,9 +103,34 @@ pub struct GrafanaDashboardSpec {
|
|||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub resync_period: Option<String>,
|
pub resync_period: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub datasources: Option<Vec<GrafanaDashboardDatasource>>,
|
||||||
|
|
||||||
pub instance_selector: LabelSelector,
|
pub instance_selector: LabelSelector,
|
||||||
|
|
||||||
pub json: String,
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub json: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub grafana_com: Option<GrafanaCom>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GrafanaDashboardDatasource {
|
||||||
|
pub input_name: String,
|
||||||
|
pub datasource_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GrafanaCom {
|
||||||
|
pub id: u32,
|
||||||
|
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub revision: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -126,6 +151,30 @@ pub struct GrafanaDatasourceSpec {
|
|||||||
pub allow_cross_namespace_import: Option<bool>,
|
pub allow_cross_namespace_import: Option<bool>,
|
||||||
|
|
||||||
pub datasource: GrafanaDatasourceConfig,
|
pub datasource: GrafanaDatasourceConfig,
|
||||||
|
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub values_from: Option<Vec<GrafanaValueFrom>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GrafanaValueFrom {
|
||||||
|
pub target_path: String,
|
||||||
|
pub value_from: GrafanaValueSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GrafanaValueSource {
|
||||||
|
pub secret_key_ref: GrafanaSecretKeyRef,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GrafanaSecretKeyRef {
|
||||||
|
pub name: String,
|
||||||
|
pub key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||||
|
@ -11,8 +11,7 @@ use std::process::Command;
|
|||||||
use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus;
|
use crate::modules::monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus;
|
||||||
use crate::modules::monitoring::kube_prometheus::crd::crd_default_rules::build_default_application_rules;
|
use crate::modules::monitoring::kube_prometheus::crd::crd_default_rules::build_default_application_rules;
|
||||||
use crate::modules::monitoring::kube_prometheus::crd::crd_grafana::{
|
use crate::modules::monitoring::kube_prometheus::crd::crd_grafana::{
|
||||||
Grafana, GrafanaDashboard, GrafanaDashboardSpec, GrafanaDatasource, GrafanaDatasourceConfig,
|
Grafana, GrafanaDashboard, GrafanaDashboardSpec, GrafanaDatasource, GrafanaDatasourceConfig, GrafanaDatasourceJsonData, GrafanaDatasourceSpec, GrafanaSecretKeyRef, GrafanaSpec, GrafanaValueFrom, GrafanaValueSource
|
||||||
GrafanaDatasourceJsonData, GrafanaDatasourceSpec, GrafanaSpec,
|
|
||||||
};
|
};
|
||||||
use crate::modules::monitoring::kube_prometheus::crd::crd_prometheus_rules::{
|
use crate::modules::monitoring::kube_prometheus::crd::crd_prometheus_rules::{
|
||||||
PrometheusRule, PrometheusRuleSpec, RuleGroup,
|
PrometheusRule, PrometheusRuleSpec, RuleGroup,
|
||||||
@ -504,6 +503,7 @@ impl K8sPrometheusCRDAlertingInterpret {
|
|||||||
is_default: None,
|
is_default: None,
|
||||||
editable: None,
|
editable: None,
|
||||||
},
|
},
|
||||||
|
values_from: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -524,7 +524,9 @@ impl K8sPrometheusCRDAlertingInterpret {
|
|||||||
spec: GrafanaDashboardSpec {
|
spec: GrafanaDashboardSpec {
|
||||||
resync_period: Some("30s".to_string()),
|
resync_period: Some("30s".to_string()),
|
||||||
instance_selector: labels.clone(),
|
instance_selector: labels.clone(),
|
||||||
json,
|
json: Some(json),
|
||||||
|
grafana_com: None,
|
||||||
|
datasources: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user