Skip to content

Commit ca09853

Browse files
Carlos Konstanskiroot
authored andcommitted
Create servicedependency objects based on tags
When a resource has a tag with the form 'parent:', create a servicedependency object. Issue: CIRRUS-4265
1 parent f8ea9c8 commit ca09853

File tree

2 files changed

+73
-50
lines changed

2 files changed

+73
-50
lines changed

examples/nagios_.jinja2

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,11 @@
1-
{% set allowed_metaparams = ('alias',) %}
2-
{% set named_objects = ('host', 'hostgroup', 'servicegroup', 'contact', 'contactgroup', 'timeperiod', 'command') %}
3-
{% set object_name = resource_type[7:] %}
4-
{% set named_object = object_name in named_objects %}
5-
{% set service_dependencies = {} %}
6-
{% for resource in resources %}
7-
{% set envs_to_ignore = [] %}
8-
{% if resource.exported %}
9-
{% if "only-cross-site" not in resource.tags or localsite == "false" %}
10-
define {{ object_name }} {
11-
{% if named_object %}
12-
{{ object_name }}_name {{ resource.name }}
1+
define {{ dto.object_name }} {
2+
{% if dto.named_object %}
3+
{{ dto.object_name }}_name {{ dto.name }}
134
{% endif %}
14-
{% for key, value in resource.parameters.items() %}
15-
{% if key not in metaparams or key in allowed_metaparams %}
16-
{% if value is iterable and value is not string %}
17-
{{ key }} {{ value|join(", ") }}
18-
{% else %}
5+
{% for item in dto.parameters %}
6+
{% for key, value in item.iteritems() %}
197
{{ key }} {{ value }}
20-
{% set _ = envs_to_ignore.append((object_name ~ '_' ~ key)|upper) %}
21-
{% endif %}
22-
{% endif %}
238
{% endfor %}
24-
{% for name in env %}
25-
{% set nameparts = name.split('_') %}
26-
{% if nameparts[0]|lower == object_name %}
27-
{% if name not in envs_to_ignore %}
28-
{{ ("_".join(nameparts[1:]))|lower }} {{ env[name]|lower }}
29-
{% endif %}
30-
{% endif %}
319
{% endfor %}
3210
}
33-
{% for tag in resource.tags %}
34-
{% if 'parent:' in tag %}
35-
{% set parent_service_description = ':'.split(tag) %}
36-
# {{ parent_service_description }}
37-
{% endif %}
38-
{% endfor %}
39-
{% endif %}
40-
{% endif %}
41-
{% endfor %}
11+

puppetdb_stencil.py

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
#!/usr/bin/env python
2+
23
"""
34
puppetdb-stencil is a tool to render puppet resources using templates.
45
"""
56

67
from __future__ import print_function
78
from __future__ import unicode_literals
8-
99
import argparse
1010
import logging
11+
import sys
1112
import os
1213
import pypuppetdb
1314
import jinja2
1415

15-
LOG = logging.getLogger('puppetdb_stencil')
16-
17-
METAPARAMS = ('require', 'before', 'subscribe', 'notify', 'audit', 'loglevel',
18-
'noop', 'schedule', 'stage', 'alias', 'tag')
1916

17+
LOG = logging.getLogger('puppetdb_stencil')
18+
METAPARAMS = ('require', 'before', 'subscribe', 'notify', 'audit', 'loglevel', 'noop', 'schedule', 'stage', 'alias', 'tag')
19+
ALLOWED_METAPARAMS = ('alias')
20+
NAMED_OBJECTS = ('host', 'hostgroup', 'servicegroup', 'servicedependency', 'contact', 'contactgroup', 'timeperiod', 'command')
2021
# Allow templates from anywhere on the filesystem
2122
LOADER = jinja2.FileSystemLoader(['.', '/'])
2223
EXTENSIONS = ['jinja2.ext.with_', 'jinja2.ext.loopcontrols']
23-
ENVIRONMENT = jinja2.Environment(trim_blocks=True, lstrip_blocks=True,
24-
loader=LOADER, extensions=EXTENSIONS)
24+
ENVIRONMENT = jinja2.Environment(trim_blocks=True, lstrip_blocks=True, loader=LOADER, extensions=EXTENSIONS)
2525

2626

2727
def render_resources(database, resource_type, localsite, template_names):
@@ -30,15 +30,69 @@ def render_resources(database, resource_type, localsite, template_names):
3030
database and rendered using the first template from template_names that can
3131
be loaded.
3232
"""
33-
resources = database.resources(resource_type)
33+
# database.resources() is a generator, but we need to iterate it twice, so make a copy
34+
r = database.resources(resource_type)
35+
resources = []
3436
try:
3537
template = ENVIRONMENT.select_template(template_names)
3638
except jinja2.TemplatesNotFound:
3739
LOG.error('No template found for {0}'.format(resource_type))
3840
else:
39-
return template.render(resource_type=resource_type,
40-
resources=resources, metaparams=METAPARAMS,
41-
env=os.environ, localsite=localsite)
41+
icinga_config = ''
42+
object_name = resource_type[7:]
43+
named_object = object_name in NAMED_OBJECTS
44+
service_dependencies = {}
45+
for resource in r:
46+
resources.append(resource)
47+
envs_to_ignore = []
48+
if resource.exported and ('only-cross-site' not in resource.tags or localsite == 'false'):
49+
dto = {}
50+
dto['object_name'] = object_name
51+
dto['named_object'] = named_object
52+
dto['name'] = resource.name
53+
dto['parameters'] = []
54+
# capture resource parameters from puppet
55+
for key, value in resource.parameters.items():
56+
if (key not in METAPARAMS or key in ALLOWED_METAPARAMS) and (isinstance(value, list)):
57+
dto['parameters'].append({key: ','.join(value)})
58+
else:
59+
dto['parameters'].append({key: value})
60+
envs_to_ignore.append((object_name + '_' + key).upper())
61+
# capture environment variable defaults
62+
for name in os.environ:
63+
nameparts = name.split('_')
64+
if nameparts[0].lower() == object_name and name not in envs_to_ignore:
65+
dto['parameters'].append({'_'.join(nameparts[1:]).lower(): os.environ[name].lower()})
66+
icinga_config += template.render(dto=dto) + '\n'
67+
# collect child service dependencies under parent service_description
68+
for tag in resource.tags:
69+
if 'parent:' in tag:
70+
parent_service_description_list = tag.split(':')
71+
if len(parent_service_description_list) == 2:
72+
parent_service_description = parent_service_description_list[1]
73+
if parent_service_description not in service_dependencies:
74+
service_dependencies[parent_service_description] = []
75+
service_dependencies[parent_service_description].append(resource)
76+
# render service dependencies
77+
if len(service_dependencies) > 0:
78+
for item in service_dependencies:
79+
parent_service_description = item.replace('_', ' ')
80+
# lookup parent resource by its service_description
81+
for parent in resources:
82+
if parent.exported and ('only-cross-site' not in parent.tags or localsite == 'false'):
83+
for key, value in parent.parameters.items():
84+
if key == 'service_description' and parent_service_description in value.lower():
85+
for child in service_dependencies[item]:
86+
dto = {}
87+
dto['object_name'] = 'servicedependency'
88+
dto['parameters'] = [{
89+
'host_name': parent.parameters['host_name'],
90+
'service_description': parent.parameters['service_description'],
91+
'dependent_host_name': child.parameters['host_name'],
92+
'dependent_service_description': child.parameters['service_description']
93+
}]
94+
icinga_config += template.render(dto=dto) + '\n'
95+
return icinga_config
4296

4397

4498
def main():
@@ -52,12 +106,9 @@ def main():
52106
parser.add_argument('--host', '-H', default='localhost')
53107
parser.add_argument('--port', '-p', default='8080')
54108
parser.add_argument('--localsite', '-l', default='true')
55-
56109
args = parser.parse_args()
57110
logging.basicConfig(level=logging.DEBUG if args.debug else logging.WARN)
58-
59111
database = pypuppetdb.connect(host=args.host, port=args.port)
60-
61112
for resource_type in args.resource_types:
62113
templates = ['{0}.jinja2'.format(resource_type)]
63114
if args.templates:
@@ -67,3 +118,5 @@ def main():
67118

68119
if __name__ == '__main__':
69120
main()
121+
sys.exit(0)
122+

0 commit comments

Comments
 (0)