-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathservice.rs
More file actions
142 lines (131 loc) · 5.2 KB
/
Copy pathservice.rs
File metadata and controls
142 lines (131 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use std::collections::BTreeMap;
use snafu::{ResultExt, Snafu};
use stackable_operator::{
builder::meta::ObjectMetaBuilder,
k8s_openapi::api::core::v1::{Service, ServicePort, ServiceSpec},
kvp::{Annotations, Labels, ObjectLabels},
role_utils::RoleGroupRef,
};
use crate::crd::{HTTPS_PORT, HTTPS_PORT_NAME, METRICS_PORT, METRICS_PORT_NAME, v1alpha1};
#[derive(Snafu, Debug)]
pub enum Error {
#[snafu(display("object is missing metadata to build owner reference"))]
ObjectMissingMetadataForOwnerRef {
source: stackable_operator::builder::meta::Error,
},
#[snafu(display("failed to build Metadata"))]
MetadataBuild {
source: stackable_operator::builder::meta::Error,
},
}
/// The rolegroup headless [`Service`] is a service that allows direct access to the instances of a certain rolegroup
/// This is mostly useful for internal communication between peers, or for clients that perform client-side load balancing.
pub fn build_rolegroup_headless_service(
nifi: &v1alpha1::NifiCluster,
role_group_ref: &RoleGroupRef<v1alpha1::NifiCluster>,
object_labels: ObjectLabels<v1alpha1::NifiCluster>,
selector: BTreeMap<String, String>,
) -> Result<Service, Error> {
Ok(Service {
metadata: ObjectMetaBuilder::new()
.name_and_namespace(nifi)
.name(role_group_ref.rolegroup_headless_service_name())
.ownerreference_from_resource(nifi, None, Some(true))
.context(ObjectMissingMetadataForOwnerRefSnafu)?
.with_recommended_labels(object_labels)
.context(MetadataBuildSnafu)?
.build(),
spec: Some(ServiceSpec {
// Internal communication does not need to be exposed
type_: Some("ClusterIP".to_string()),
cluster_ip: Some("None".to_string()),
ports: Some(headless_service_ports()),
selector: Some(selector),
publish_not_ready_addresses: Some(true),
..ServiceSpec::default()
}),
status: None,
})
}
/// The rolegroup metrics [`Service`] is a service that exposes metrics and a prometheus scraping label.
pub fn build_rolegroup_metrics_service(
nifi: &v1alpha1::NifiCluster,
role_group_ref: &RoleGroupRef<v1alpha1::NifiCluster>,
object_labels: ObjectLabels<v1alpha1::NifiCluster>,
selector: BTreeMap<String, String>,
product_version: &str,
) -> Result<Service, Error> {
Ok(Service {
metadata: ObjectMetaBuilder::new()
.name_and_namespace(nifi)
.name(role_group_ref.rolegroup_metrics_service_name())
.ownerreference_from_resource(nifi, None, Some(true))
.context(ObjectMissingMetadataForOwnerRefSnafu)?
.with_recommended_labels(object_labels)
.context(MetadataBuildSnafu)?
.with_labels(prometheus_labels())
.with_annotations(prometheus_annotations(product_version))
.build(),
spec: Some(ServiceSpec {
// Internal communication does not need to be exposed
type_: Some("ClusterIP".to_string()),
cluster_ip: Some("None".to_string()),
ports: Some(vec![metrics_service_port(product_version)]),
selector: Some(selector),
publish_not_ready_addresses: Some(true),
..ServiceSpec::default()
}),
status: None,
})
}
fn headless_service_ports() -> Vec<ServicePort> {
vec![ServicePort {
name: Some(HTTPS_PORT_NAME.into()),
port: HTTPS_PORT.into(),
protocol: Some("TCP".to_string()),
..ServicePort::default()
}]
}
/// Returns the metrics port based on the NiFi version
/// V1: Uses extra port via JMX exporter
/// V2: Uses NiFi HTTP(S) port for metrics
pub fn metrics_service_port(product_version: &str) -> ServicePort {
if product_version.starts_with("1.") {
ServicePort {
name: Some(METRICS_PORT_NAME.to_string()),
port: METRICS_PORT.into(),
protocol: Some("TCP".to_string()),
..ServicePort::default()
}
} else {
ServicePort {
name: Some(HTTPS_PORT_NAME.into()),
port: HTTPS_PORT.into(),
protocol: Some("TCP".to_string()),
..ServicePort::default()
}
}
}
/// Common labels for Prometheus
fn prometheus_labels() -> Labels {
Labels::try_from([("prometheus.io/scrape", "true")]).expect("should be a valid label")
}
/// Common annotations for Prometheus
///
/// These annotations can be used in a ServiceMonitor.
///
/// see also <https://github.com/prometheus-community/helm-charts/blob/prometheus-27.32.0/charts/prometheus/values.yaml#L983-L1036>
fn prometheus_annotations(product_version: &str) -> Annotations {
let (path, port, scheme) = if product_version.starts_with("1.") {
("/metrics", METRICS_PORT, "http")
} else {
("/nifi-api/flow/metrics/prometheus", HTTPS_PORT, "https")
};
Annotations::try_from([
("prometheus.io/path".to_owned(), path.to_owned()),
("prometheus.io/port".to_owned(), port.to_string()),
("prometheus.io/scheme".to_owned(), scheme.to_owned()),
("prometheus.io/scrape".to_owned(), "true".to_owned()),
])
.expect("should be valid annotations")
}