1
1
# Copyright 2014-2015 Canonical Limited.
3
# This file is part of charm-helpers.
5
# charm-helpers is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU Lesser General Public License version 3 as
7
# published by the Free Software Foundation.
9
# charm-helpers is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU Lesser General Public License for more details.
14
# You should have received a copy of the GNU Lesser General Public License
15
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
19
18
from charmhelpers.core import host
20
19
from charmhelpers.core import hookenv
23
22
def render(source, target, context, owner='root', group='root',
24
perms=0o444, templates_dir=None, encoding='UTF-8'):
23
perms=0o444, templates_dir=None, encoding='UTF-8', template_loader=None):
28
27
The `source` path, if not absolute, is relative to the `templates_dir`.
30
The `target` path should be absolute.
29
The `target` path should be absolute. It can also be `None`, in which
30
case no file will be written.
32
32
The context should be a dict containing the values to be replaced in the
37
37
If omitted, `templates_dir` defaults to the `templates` folder in the charm.
39
Note: Using this requires python-jinja2; if it is not installed, calling
40
this will attempt to use charmhelpers.fetch.apt_install to install it.
39
The rendered template will be written to the file as well as being returned
42
Note: Using this requires python-jinja2 or python3-jinja2; if it is not
43
installed, calling this will attempt to use charmhelpers.fetch.apt_install
43
47
from jinja2 import FileSystemLoader, Environment, exceptions
49
53
'charmhelpers.fetch to install it',
50
54
level=hookenv.ERROR)
52
apt_install('python-jinja2', fatal=True)
56
if sys.version_info.major == 2:
57
apt_install('python-jinja2', fatal=True)
59
apt_install('python3-jinja2', fatal=True)
53
60
from jinja2 import FileSystemLoader, Environment, exceptions
55
if templates_dir is None:
56
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
57
loader = Environment(loader=FileSystemLoader(templates_dir))
63
template_env = Environment(loader=template_loader)
65
if templates_dir is None:
66
templates_dir = os.path.join(hookenv.charm_dir(), 'templates')
67
template_env = Environment(loader=FileSystemLoader(templates_dir))
60
template = loader.get_template(source)
70
template = template_env.get_template(source)
61
71
except exceptions.TemplateNotFound as e:
62
72
hookenv.log('Could not load template %s from %s.' %
63
73
(source, templates_dir),
64
74
level=hookenv.ERROR)
66
76
content = template.render(context)
67
host.mkdir(os.path.dirname(target), owner, group, perms=0o755)
68
host.write_file(target, content.encode(encoding), owner, group, perms)
77
if target is not None:
78
target_dir = os.path.dirname(target)
79
if not os.path.exists(target_dir):
80
# This is a terrible default directory permission, as the file
81
# or its siblings will often contain secrets.
82
host.mkdir(os.path.dirname(target), owner, group, perms=0o755)
83
host.write_file(target, content.encode(encoding), owner, group, perms)