2 """Fetch dashboards from provided urls into this chart."""
5 from os import makedirs, path
9 from yaml.representer import SafeRepresenter
12 # https://stackoverflow.com/a/20863889/961092
13 class LiteralStr(str):
17 def change_style(style, representer):
18 def new_representer(dumper, data):
19 scalar = representer(dumper, data)
23 return new_representer
29 'source': 'https://raw.githubusercontent.com/coreos/prometheus-operator/master/contrib/kube-prometheus/manifests/grafana-dashboardDefinitions.yaml',
30 'destination': '../templates/grafana/dashboards',
34 'source': 'https://raw.githubusercontent.com/etcd-io/etcd/master/Documentation/op-guide/grafana.json',
35 'destination': '../templates/grafana/dashboards',
39 'source': 'https://raw.githubusercontent.com/helm/charts/master/stable/prometheus-operator/dashboards/grafana-coredns-k8s.json',
40 'destination': '../templates/grafana/dashboards',
45 # Additional conditions map
47 'grafana-coredns-k8s': ' .Values.coreDns.enabled',
48 'etcd': ' .Values.kubeEtcd.enabled',
52 header = '''# Generated from '%(name)s' from %(url)s
53 {{- if and .Values.grafana.enabled .Values.grafana.defaultDashboardsEnabled%(condition)s }}
57 name: {{ printf "%%s-%%s" (include "prometheus-operator.fullname" $) "%(name)s" | trunc 63 | trimSuffix "-" }}
59 {{- if $.Values.grafana.sidecar.dashboards.label }}
60 {{ $.Values.grafana.sidecar.dashboards.label }}: "1"
62 app: {{ template "prometheus-operator.name" $ }}-grafana
63 {{ include "prometheus-operator.labels" $ | indent 4 }}
68 def init_yaml_styles():
69 represent_literal_str = change_style('|', SafeRepresenter.represent_str)
70 yaml.add_representer(LiteralStr, represent_literal_str)
74 return s.replace("{{", "{{`{{").replace("}}", "}}`}}")
77 def yaml_str_repr(struct, indent=2):
78 """represent yaml as a string"""
81 width=1000, # to disable line wrapping
82 default_flow_style=False # to disable multiple items on single line
84 text = escape(text) # escape {{ and }} for helm
85 text = textwrap.indent(text, ' ' * indent)
89 def write_group_to_file(resource_name, content, url, destination):
92 'name': resource_name,
94 'condition': condition_map.get(resource_name, ''),
97 filename_struct = {resource_name + '.json': (LiteralStr(content))}
99 lines += yaml_str_repr(filename_struct)
102 lines += '{{- end }}'
104 filename = resource_name + '.yaml'
105 new_filename = "%s/%s" % (destination, filename)
107 # make sure directories to store the file exist
108 makedirs(destination, exist_ok=True)
111 with open(new_filename, 'w') as f:
114 print("Generated %s" % new_filename)
119 # read the rules, create a new template file per group
121 print("Generating rules from %s" % chart['source'])
122 raw_text = requests.get(chart['source']).text
123 if chart['type'] == 'yaml':
124 yaml_text = yaml.load(raw_text)
125 groups = yaml_text['items']
127 for resource, content in group['data'].items():
128 write_group_to_file(resource.replace('.json', ''), content, chart['source'], chart['destination'])
129 elif chart['type'] == 'json':
130 json_text = json.loads(raw_text)
131 # is it already a dashboard structure or is it nested (etcd case)?
132 flat_structure = bool(json_text.get('annotations'))
134 resource = path.basename(chart['source']).replace('.json', '')
135 write_group_to_file(resource, json.dumps(json_text, indent=4), chart['source'], chart['destination'])
137 for resource, content in json_text.items():
138 write_group_to_file(resource.replace('.json', ''), json.dumps(content, indent=4), chart['source'], chart['destination'])
142 if __name__ == '__main__':