kubezero/charts/kubezero-metrics/sync_grafana_dashboards.py

152 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import json
import yaml
import requests
import textwrap
import io
import gzip
import base64
config_file = sys.argv[1]
configmap_file = sys.argv[2]
def traverse_json(obj):
if isinstance(obj, dict):
for k, v in obj.items():
# CloudBender::StackRef
if k == "datasource" and v:
obj[k] = "Prometheus"
if isinstance(v, dict) or isinstance(v, list):
traverse_json(v)
elif isinstance(obj, list):
for k in obj:
if isinstance(k, dict) or isinstance(k, list):
traverse_json(k)
# read config file
with open(config_file, "r") as yaml_contents:
config = yaml.safe_load(yaml_contents.read())
configmap = ""
if "condition" in config:
# use index function to make go template happy if '-' in names
if "-" in config["condition"] and "index" not in config["condition"]:
tokens = config["condition"].split(".")
configmap = """{{- if index .Values %(condition)s }}
""" % {
"condition": " ".join(f'"{w}"' for w in tokens[2:])
}
else:
configmap = (
"""{{- if %(condition)s }}
"""
% config
)
# Base configmap for KubeZero
configmap += (
"""apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%%s-%%s" (include "kubezero-lib.fullname" $) "%(configmap)s" | trunc 63 | trimSuffix "-" }}
namespace: {{ .Release.Namespace }}
labels:
grafana_dashboard: "1"
{{- include "kubezero-lib.labels" . | nindent 4 }}
"""
% config
)
# Put all dashboards into a folder ?
if "folder" in config:
configmap += (
""" annotations:
k8s-sidecar-target-directory: %(folder)s
"""
% config
)
# compress ?
if "gzip" in config and config["gzip"]:
configmap += """binaryData:
"""
else:
configmap += """data:
"""
for b in config["dashboards"]:
if not b["url"].startswith("file://"):
response = requests.get(b["url"])
if response.status_code != 200:
print(
"Skipping the file, response code %s not equals 200"
% response.status_code
)
continue
raw_text = response.text
else:
with open(b["url"].replace("file://", ""), "r") as file_contents:
raw_text = file_contents.read()
obj = json.loads(raw_text)
# replace datasources
traverse_json(obj)
# Set default tim in all charts to 1h
obj["time"] = {"from": "now-1h", "to": "now"}
obj["refresh"] = "30s"
# set tags
if "tags" in b:
obj["tags"] = b["tags"]
text = json.dumps(obj, indent=2)
if "gzip" in config and config["gzip"]:
# compress and base64 encode
buf = io.BytesIO()
f = gzip.GzipFile(mode="w", fileobj=buf, mtime=0)
f.write(text.encode())
f.close()
textb64 = base64.b64encode(buf.getvalue()).decode("utf-8")
textb64 = textwrap.indent(textb64, " " * 4)
configmap += (
""" %(name)s.json.gz:
"""
% b
)
configmap += textb64 + "\n"
else:
# encode otherwise helm will mess with raw json
text = (
text.replace("{{", "{{`{{")
.replace("}}", "}}`}}")
.replace("{{`{{", "{{`{{`}}")
.replace("}}`}}", "{{`}}`}}")
)
text = textwrap.indent(text, " " * 4)
configmap += (
""" %(name)s.json:
"""
% b
)
configmap += text + "\n"
if "condition" in config:
configmap += "{{- end }}" + "\n"
# Write Configmap
with open(configmap_file, "w") as f:
f.write(configmap)