Skip to content

Commit

Permalink
Merge pull request #49 from OpenNMS/deejgregor/horizon-multi-tenant-o…
Browse files Browse the repository at this point in the history
…ptional

Make multi-tenant support and release namespace optional
  • Loading branch information
deejgregor authored Nov 22, 2023
2 parents 3b61072 + b59c276 commit 833ee09
Show file tree
Hide file tree
Showing 35 changed files with 165 additions and 72 deletions.
2 changes: 1 addition & 1 deletion horizon/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.1.5
version: 1.1.6

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
Expand Down
4 changes: 3 additions & 1 deletion horizon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ kubectl create configmap -n $instance $configmap --from-file=lots-of-zeros.zip
| core.resources.requests.cpu | string | `"2"` | |
| core.resources.requests.memory | string | `"4Gi"` | |
| core.terminationGracePeriodSeconds | int | `120` | |
| createNamespace | bool | `false` | |
| createNamespace | bool | `false` | Whether to create the namespace when releaseNamespace=true. Has no effect otherwise. |
| dependencies.clusterRole | bool | `true` | |
| dependencies.clusterRoleBinding | bool | `true` | |
| dependencies.cortex.bulkheadMaxWaitDuration | string | `"9223372036854775807"` | |
Expand Down Expand Up @@ -211,11 +211,13 @@ kubectl create configmap -n $instance $configmap --from-file=lots-of-zeros.zip
| ingress.annotations | object | `{}` | |
| ingress.certManager.clusterIssuer | string | `"opennms-issuer"` | |
| ingress.className | string | `"nginx"` | |
| multiTenant | bool | `false` | Enable multi-tenant mode. This will use the release name as the per-tenant identifier for the OpenNMS instance ID, databases, Kakfa topics, ElasticSearch indices, and Prometheus organization ID. |
| promtail.image.pullPolicy | string | `"IfNotPresent"` | |
| promtail.image.repository | string | `"grafana/promtail"` | |
| promtail.image.tag | string | `"latest"` | |
| promtail.resources.limits.cpu | string | `"50m"` | |
| promtail.resources.limits.memory | string | `"64Mi"` | |
| releaseNamespace | bool | `false` | Install resource objects into namespace named for the Helm release. See also createNamespace. |
| sentinel.configuration.database.poolSize | int | `25` | |
| sentinel.image.pullPolicy | string | `"IfNotPresent"` | |
| sentinel.image.repository | string | `"opennms/sentinel"` | |
Expand Down
37 changes: 26 additions & 11 deletions horizon/scripts/onms-core-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,17 @@ mkdir -p ${CONFIG_DIR_OVERLAY}/opennms.properties.d ${CONFIG_DIR_OVERLAY}/featur
# Apply common OpenNMS configuration settings
# Configure the instance ID
# Required when having multiple OpenNMS backends sharing a Kafka cluster or an Elasticsearch cluster.
if [[ ${OPENNMS_INSTANCE_ID} ]]; then
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
echo "Creating ${CONFIG_DIR_OVERLAY}/opennms.properties.d/instanceid.properties with our instance ID '${OPENNMS_INSTANCE_ID}'"
cat <<EOF > ${CONFIG_DIR_OVERLAY}/opennms.properties.d/instanceid.properties
# Used for Kafka Topics and Elasticsearch Index Prefixes
org.opennms.instance.id=${OPENNMS_INSTANCE_ID}
EOF
else
OPENNMS_INSTANCE_ID="OpenNMS"
if [[ -e "${CONFIG_DIR}/opennms.properties.d/instanceid.properties" ]]; then
echo "Found ${CONFIG_DIR}/opennms.properties.d/instanceid.properties, we are going to remove it."
rm "${CONFIG_DIR}/opennms.properties.d/instanceid.properties"
fi
fi

# Disable data choices (optional)
Expand Down Expand Up @@ -393,8 +396,10 @@ readTimeoutInMs=${CORTEX_READ_TIMEOUT}
metricCacheSize=${CORTEX_METRIC_CACHE_SIZE}
externalTagsCacheSize=${CORTEX_EXTERNAL_TAGS_CACHE_SIZE}
bulkheadMaxWaitDuration=${CORTEX_BULKHEAD_MAX_WAIT_DURATION}
organizationId=${OPENNMS_INSTANCE_ID}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
echo "organizationId=${OPENNMS_INSTANCE_ID}" >> ${CONFIG_DIR_OVERLAY}/org.opennms.plugins.tss.cortex.cfg
fi

mkdir -p ${CONFIG_DIR_OVERLAY}/featuresBoot.d

Expand Down Expand Up @@ -440,15 +445,19 @@ EOF
# Configure Elasticsearch to allow Helm/Grafana to access Flow data
if [[ -v ELASTICSEARCH_SERVER ]]; then
echo "Configuring Elasticsearch for Flows..."
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
echo "Creating ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg"
cat <<EOF > ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg
elasticUrl=https://${ELASTICSEARCH_SERVER}
globalElasticUser=${ELASTICSEARCH_USER}
globalElasticPassword=${ELASTICSEARCH_PASSWORD}
elasticIndexStrategy=${ELASTICSEARCH_INDEX_STRATEGY_FLOWS}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg
indexPrefix=${PREFIX}
EOF
fi
fi


Expand Down Expand Up @@ -478,11 +487,6 @@ fi

# Configure Sink and RPC to use Kafka, and the Kafka Producer.
if [[ -v KAFKA_BOOTSTRAP_SERVER ]]; then
if [[ ${OPENNMS_INSTANCE_ID} == "" ]]; then
echo >&2 "OPENNMS_INSTANCE_ID cannot be empty. Aborting."
exit 1
fi

echo "Configuring Kafka for IPC..."

echo "Creating ${CONFIG_DIR_OVERLAY}/opennms.properties.d/amq.properties"
Expand All @@ -500,16 +504,19 @@ EOF
# TWIN
org.opennms.core.ipc.twin.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties
org.opennms.core.ipc.twin.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Twin
EOF
fi
fi

cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties
# SINK
org.opennms.core.ipc.sink.initialSleepTime=60000
org.opennms.core.ipc.sink.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
org.opennms.core.ipc.sink.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Sink
# SINK Consumer (verify Kafka broker configuration)
org.opennms.core.ipc.sink.kafka.session.timeout.ms=30000
Expand All @@ -519,7 +526,6 @@ org.opennms.core.ipc.sink.kafka.max.poll.records=50
org.opennms.core.ipc.rpc.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
org.opennms.core.ipc.rpc.kafka.ttl=30000
org.opennms.core.ipc.rpc.kafka.single-topic=true
org.opennms.core.ipc.rpc.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-RPC
# RPC Consumer (verify Kafka broker configuration)
org.opennms.core.ipc.rpc.kafka.request.timeout.ms=30000
Expand All @@ -532,6 +538,15 @@ org.opennms.core.ipc.rpc.kafka.acks=0
org.opennms.core.ipc.rpc.kafka.linger.ms=5
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties
# org.opennms.instance.id-prefixed groups for multi-tenant operation
org.opennms.core.ipc.sink.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Sink
org.opennms.core.ipc.rpc.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-RPC
EOF
fi

MODULES="rpc sink"
if [[ "$USE_TWIN" == "true" ]]; then
MODULES="twin $MODULES"
Expand Down
24 changes: 15 additions & 9 deletions horizon/scripts/onms-sentinel-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,12 @@ OVERLAY_DIR=/opt/sentinel-etc-overlay

# Configure the instance ID and Interface-to-Node cache
# Required when having multiple OpenNMS backends sharing a Kafka cluster or an Elasticsearch cluster.
CUSTOM_PROPERTIES=${OVERLAY_DIR}/custom.system.properties
if [[ ${OPENNMS_INSTANCE_ID} ]]; then
cat <<EOF >> ${CUSTOM_PROPERTIES}
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${OVERLAY_DIR}/custom.system.properties
# Used for Kafka Topics
org.opennms.instance.id=${OPENNMS_INSTANCE_ID}
# Refresh Interface-to-Node cache every 2 hours
org.opennms.interface-node-cache.refresh-timer=7200000
EOF
else
OPENNMS_INSTANCE_ID="OpenNMS"
fi
cat <<EOF > ${OVERLAY_DIR}/org.opennms.netmgt.distributed.datasource.cfg
Expand Down Expand Up @@ -122,17 +118,22 @@ adapters.0.class-name=org.opennms.netmgt.telemetry.protocols.netflow.adapter.net
queue.threads=${NUM_LISTENER_THREADS}
EOF

PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF > ${OVERLAY_DIR}/org.opennms.features.flows.persistence.elastic.cfg
elasticUrl=https://${ELASTICSEARCH_SERVER}
globalElasticUser=${ELASTICSEARCH_USER}
globalElasticPassword=${ELASTICSEARCH_PASSWORD}
elasticIndexStrategy=${ELASTICSEARCH_INDEX_STRATEGY_FLOWS}
indexPrefix=${PREFIX}
# The following settings should be consistent with your ES cluster
settings.index.number_of_shards=${ELASTICSEARCH_NUM_SHARDS}
settings.index.number_of_replicas=${ELASTICSEARCH_REPLICATION_FACTOR}
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF >> ${OVERLAY_DIR}/org.opennms.features.flows.persistence.elastic.cfg
indexPrefix=${PREFIX}
EOF
fi
fi

if [[ -v KAFKA_BOOTSTRAP_SERVER ]]; then
Expand All @@ -149,11 +150,16 @@ EOF

cat <<EOF > ${FILE_PREFIX}.consumer.cfg
# Consumers
group.id=${OPENNMS_INSTANCE_ID}_Sentinel
bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
max.partition.fetch.bytes=5000000
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${FILE_PREFIX}.consumer.cfg
group.id=${OPENNMS_INSTANCE_ID}_Sentinel
EOF
fi

for f in ${FILE_PREFIX}.cfg ${FILE_PREFIX}.consumer.cfg; do
cat <<EOF >> $f
# Security
Expand Down
45 changes: 36 additions & 9 deletions horizon/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
{{/*
Define namespace option for Helm commands
*/}}
{{- define "helm.namespace" -}}
{{- if ne .Release.Namespace "default" }}
{{- printf " -n %s" .Release.Namespace }}
{{- else }}
{{- printf "" }}
{{- end }}
{{- end }}

{{/*
Define namespace option for kubectl commands
*/}}
{{- define "kubectl.namespace" -}}
{{- if ne (include "namespace" .) "default" }}
{{- printf " -n %s" (include "namespace" .) }}
{{- else }}
{{- printf "" }}
{{- end }}
{{- end }}

Thank you for installing OpenNMS {{ .Values.core.image.tag | default .Chart.AppVersion }}.

Your release is named "{{ .Release.Name }}", used for:
Your release is named "{{ .Release.Name }}" and is installed into the
"{{ include "namespace" . }}" namespace. The release name is used as
the sub-domain for the ingress controller.
{{- if .Values.multiTenant }}

Multi-tenant mode is enabled, so the release name "{{ .Release.Name }}"
is also used for:
- Customer/Deployment identifier.
- The namespace for all the resources.
- The sub-domain for the ingress controller.
- Prefix for PostgreSQL database names.
- The OpenNMS instance ID for your Minions (prefix for Kafka topics).
- Prefix for Elasticsearch indices.
- Prefix for PostgreSQL database names.
- Prefix for Kafka consumer groups.
{{- end }}

{{- if eq (include "onOpenShift" .) "true" }}

Expand Down Expand Up @@ -36,16 +63,16 @@ Resources URLs:

To learn more about the release, try:

$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
$ kubectl get all -n {{ .Release.Name }}
$ helm status {{ .Release.Name }}{{ include "helm.namespace" . }}
$ helm get all {{ .Release.Name }}{{ include "helm.namespace" . }}
$ kubectl get all -l app.kubernetes.io/name={{ .Release.Name }},app.kubernetes.io/instance={{ .Release.Name }}{{ include "kubectl.namespace" . }}
{{- end }}

{{- if not .Values.core.configuration.alwaysRollDeployment }}

If OpenNMS needs to be restarted to apply configuration changes, you'll need to restart it, e.g.:

$ kubectl rollout restart -n {{ .Release.Name }} statefulset/onms-core
$ kubectl rollout restart{{ include "kubectl.namespace" . }} statefulset/onms-core
{{- end }}

{{- if .Values.core.inspector.enabled }}
Expand All @@ -54,5 +81,5 @@ The inspector pod is enabled and OpenNMS pod is not running.

This is how you can connect to the inspector pod:

$ kubectl exec -it -n {{ .Release.Name }} pods/inspector -- /bin/bash
$ kubectl exec -it{{ include "kubectl.namespace" . }} pods/inspector -- /bin/bash
{{- end }}
19 changes: 16 additions & 3 deletions horizon/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ server:
http_listen_port: 9080
grpc_listen_port: 0
clients:
- tenant_id: {{ .Release.Name }}
url: {{ printf "%s://%s:%d/loki/api/v1/push" $scheme ((.Values.dependencies).loki).hostname (((.Values.dependencies).loki).port | int) }}
- url: {{ printf "%s://%s:%d/loki/api/v1/push" $scheme ((.Values.dependencies).loki).hostname (((.Values.dependencies).loki).port | int) }}
{{- if and ((.Values.dependencies).loki).username ((.Values.dependencies).loki).password }}
basic_auth:
username: {{ .Values.dependencies.loki.username }}
Expand All @@ -108,8 +107,11 @@ clients:
tls_config:
ca_file: /etc/jks/loki-ca.cert
{{- end }}
{{- if .Values.multiTenant }}
tenant_id: {{ .Release.Name }}
{{- end }}
external_labels:
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
scrape_configs:
- job_name: system
pipeline_stages:
Expand Down Expand Up @@ -148,3 +150,14 @@ Are we running in an Red Hat OpenShift cluster?
{{- printf "false" -}}
{{- end }}
{{- end }}

{{/*
Define Namespace
*/}}
{{- define "namespace" -}}
{{- if .Values.releaseNamespace }}
{{- printf "%s" .Release.Name -}}
{{- else }}
{{- printf "%s" .Release.Namespace -}}
{{- end }}
{{- end }}
2 changes: 1 addition & 1 deletion horizon/templates/app-credentials.secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: Secret
type: Opaque
metadata:
name: app-credentials
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand Down
2 changes: 1 addition & 1 deletion horizon/templates/app-jks.secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: Secret
type: Opaque
metadata:
name: app-jks
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data: # To be mounted at /etc/java/jks
Expand Down
2 changes: 1 addition & 1 deletion horizon/templates/app-scripts.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: app-scripts
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand Down
18 changes: 15 additions & 3 deletions horizon/templates/app-settings.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand All @@ -19,9 +19,17 @@ data:
ENABLE_CORTEX: {{ ((.Values.core).configuration).enableCortex | quote }}
ENABLE_TSS_DUAL_WRITE: {{ ((.Values.core).configuration).enableTssDualWrite | quote }}
ENABLE_GRAFANA: {{ if gt ((.Values.grafana).replicaCount|int) 0 }}"true"{{ else }}"false"{{ end }}
{{- if .Values.multiTenant }}
OPENNMS_INSTANCE_ID: {{ .Release.Name | quote }}
OPENNMS_SERVER: {{ printf "onms-core.%s.svc" .Release.Name | quote }}
{{- else }}
OPENNMS_INSTANCE_ID: ""
{{- end }}
OPENNMS_SERVER: {{ include "namespace" . | printf "onms-core.%s.svc" | quote }}
{{- if .Values.multiTenant }}
OPENNMS_DBNAME: {{ printf "%s_opennms" .Release.Name | quote }}
{{- else }}
OPENNMS_DBNAME: "opennms"
{{- end }}
{{- if ((.Values.core).configuration).rras }}
OPENNMS_RRAS: {{ join ";" .Values.core.configuration.rras }}
{{- end }}
Expand All @@ -47,7 +55,7 @@ data:
KAFKA_SASL_MECHANISM: {{ .Values.dependencies.kafka.configuration.saslMechanism | quote }}
KAFKA_SECURITY_PROTOCOL: {{ .Values.dependencies.kafka.configuration.securityProtocol | quote }}
{{- end }}
GRAFANA_SERVER: {{ printf "grafana.%s.svc" .Release.Name | quote }}
GRAFANA_SERVER: {{ include "namespace" . | printf "grafana.%s.svc" | quote }}
{{- if eq (include "onOpenShift" .) "true" }}
GF_SERVER_DOMAIN: {{ printf "grafana-%s" (include "core.domain" .) | quote }} # Should match FQDN on the Ingress
GF_SERVER_ROOT_URL: ""
Expand All @@ -56,7 +64,11 @@ data:
GF_SERVER_ROOT_URL: "/"
{{- end }}
GF_DATABASE_TYPE: "postgres"
{{- if .Values.multiTenant }}
GF_DATABASE_NAME: {{ printf "%s_grafana" .Release.Name | quote }}
{{- else }}
GF_DATABASE_NAME: "grafana"
{{- end }}
GF_DATABASE_SSL_MODE: {{ (((.Values.grafana).configuration).database).sslmode | default "disable" | quote }}
GF_DATABASE_CA_CERT_PATH: "/etc/java/jks/postgresql-ca.crt"
GF_SESSION_PROVIDER: "postgres"
Expand Down
Loading

0 comments on commit 833ee09

Please sign in to comment.