Commit 62f55c69 authored by Julien Muchembled's avatar Julien Muchembled

Update doc & tests

parent 46493e12
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
slapos.recipe.template slapos.recipe.template
====================== ======================
Template recipe which supports remote resource. .. contents::
Inspired by collective.recipe.template, with minimum set of features, but with Collection of recipes to generate a file from a template that can be
(hopefully) safer buildout-based templating. either inline or fetched with the buildout download API.
"jinja2" entry point allows rendering jinja2 templates. Inspired by `collective.recipe.template`.
This diff is collapsed.
Usage --------------
===== default recipe
--------------
Getting started The default recipe generates a file (option ``output``) from a template using
--------------- buildout expansion. The template is specified with either ``url`` (optionally
combined with ``md5sum``) or ``inline``.
You can start by a simple buildout:: Here is a simple buildout::
>>> write('buildout.cfg', >>> base = """
... '''
... [buildout] ... [buildout]
... parts = template ... parts = template
... ...
... [section]
... option = value
...
... [template] ... [template]
... recipe = slapos.recipe.template ... recipe = slapos.recipe.template
... url = template.in ... url = template.in
... output = template.out ... output = template.out
... ... """
... [section] >>> write('buildout.cfg', base)
... option = value
... ''')
And a simple template:: A simple template::
>>> write('template.in', '${section:option}') >>> write('template.in', '${section:option}')
We run buildout:: And the output file has been parsed by buildout itself::
>>> run_buildout() >>> run_buildout()
Installing template. Installing template.
And the output file has been parsed by buildout itself::
>>> cat('template.out') >>> cat('template.out')
value value
Full options The recipe relies on buildout expansion to pull sections it depends on, which
------------ implies that the rendering (including the download if requested) is done during
the initialization phase.
There is two non required options:
``md5sum``
Check the integrity of the input file.
``mode`` Options
Specify the filesystem permissions in octal notation. -------
Check file integrity ``md5sum`` - check file integrity
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let's write a file template:: If the template is specified with the ``url`` option, an MD5 checksum can be
given to check the contents of the template::
>>> write('template.in', '${buildout:parts}')
Compute its MD5 sum::
>>> from hashlib import md5
>>> with open('template.in', 'rb') as f:
... md5sum = md5(f.read()).hexdigest()
Write the ``buildout.cfg`` using slapos.recipe.template::
>>> write('buildout.cfg',
... '''
... [buildout]
... parts = template
...
... [template]
... recipe = slapos.recipe.template
... url = template.in
... output = template.out
... md5sum = ''' + md5sum + '''
... ''')
And run buildout, and see the result::
>>> base += """
... md5sum = 1993226f57db37c4a19cb785f826a1aa
... """
>>> write(sample_buildout, 'buildout.cfg', base)
>>> run_buildout() >>> run_buildout()
Uninstalling template. Uninstalling template.
Installing template. Installing template.
>>> cat('template.out') >>> cat('template.out')
template value
If the md5sum doesn't match, the buildout fail:: In such case, updating the part does nothing::
>>> write('buildout.cfg', >>> write('template.out', 'altered')
... '''
... [buildout]
... parts = template
...
... [template]
... recipe = slapos.recipe.template
... url = template.in
... output = template.out
... md5sum = 0123456789abcdef0123456789abcdef
... ''')
>>> run_buildout() >>> run_buildout()
Updating template.
>>> cat('template.out')
altered
In case of checksum mismatch::
>>> run_buildout('template:md5sum=00000000000000000000000000000000')
While: While:
Installing. Installing.
Getting section template. Getting section template.
Initializing section template. Initializing section template.
Error: MD5 checksum mismatch for local resource at 'template.in'. Error: MD5 checksum mismatch for local resource at 'template.in'.
``inline``
~~~~~~~~~~
Specify filesystem permissions You may prefer to inline small templates::
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can specify the mode of the written file:: >>> write('buildout.cfg', """
>>> write('template.in', '${buildout:installed}')
>>> write('buildout.cfg',
... '''
... [buildout] ... [buildout]
... parts = template ... parts = template
... ...
... [template] ... [section]
... recipe = slapos.recipe.template ... option = inlined
... url = template.in
... output = template.out
... mode = 0627
... ''')
>>> run_buildout()
Uninstalling template.
Installing template.
And the generated file with have the right permissions::
>>> import os, stat
>>> print("0%o" % stat.S_IMODE(os.stat('template.out').st_mode))
0627
Fetching template source from an URL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can fetch resources from an URL::
>>> server_data = tmpdir('server_data')
>>> server_url = start_server(server_data)
>>> write(server_data, 'template.in', '${buildout:parts}')
>>> write('buildout.cfg', '''
... [buildout]
... parts = template
... ...
... [template] ... [template]
... recipe = slapos.recipe.template ... recipe = slapos.recipe.template
... url = %stemplate.in ... inline = ${section:option}
... md5sum = %s
... output = template.out ... output = template.out
... ... """)
... ''' % (server_url, md5sum))
>>> run_buildout() >>> run_buildout()
Downloading http://localhost/template.in
Cannot download http://localhost/template.in from network cache.
Uninstalling template. Uninstalling template.
Installing template. Installing template.
>>> cat('template.out') >>> cat('template.out')
template inlined
Section dependency Note that in such case, the rendering is done by buildout itself:
------------------ it just creates a file with the value of ``inline``.
You can use other part of buildout in the template. This way this parts ``mode`` - specify filesystem permissions
will be installed as dependency:: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> write('template.in', '${dependency:foobar}') By default, executable permissions are set if the content of the output file
>>> write('buildout.cfg', ''' looks like an executable script, i.e. it has a shebang that points to an
... [buildout] executable file. This is done by respecting umask::
... parts = template
...
... [template]
... recipe = slapos.recipe.template
... url = template.in
... output = template.out
...
... [dependency]
... foobar = dependency content
... recipe = zc.buildout:debug
... ''')
>>> run_buildout() >>> import os, stat
>>> os.access('template.out', os.X_OK)
False
>>> run_buildout('section:option=#!/bin/sh')
Uninstalling template. Uninstalling template.
Installing dependency.
foobar='dependency content'
recipe='zc.buildout:debug'
Installing template. Installing template.
>>> os.access('template.out', os.X_OK)
True
This way you can get options which are computed in the ``__init__`` of File permissions can be forced using the ``mode`` option in octal representation
the dependent recipe. (no need for 0-prefix)::
Let's create a sample recipe modifying its option dict::
>>> write('setup.py',
... '''
... from setuptools import setup
...
... setup(name='samplerecipe',
... entry_points = {
... 'zc.buildout': [
... 'default = main:Recipe',
... ],
... }
... )
... ''')
>>> write('main.py',
... '''
... class Recipe(object):
...
... def __init__(self, buildout, name, options):
... options['data'] = 'foobar'
...
... def install(self):
... return []
... ''')
Let's just use ``buildout.cfg`` using this egg::
>>> write('template.in', '${sample:data}') >>> run_buildout('template:mode=627')
>>> write('buildout.cfg',
... '''
... [buildout]
... develop = .
... parts = template
...
... [template]
... recipe = slapos.recipe.template
... url = template.in
... output = template.out
...
... [sample]
... recipe = samplerecipe
... ''')
>>> run_buildout()
Develop: '/sample-buildout/.'
Uninstalling template. Uninstalling template.
Uninstalling dependency.
Installing sample.
Installing template. Installing template.
>>> cat('template.out') >>> print(oct(stat.S_IMODE(os.stat('template.out').st_mode)))
foobar 0627
...@@ -42,7 +42,8 @@ def setUp(test): ...@@ -42,7 +42,8 @@ def setUp(test):
testing.buildoutSetUp(test) testing.buildoutSetUp(test)
testing.install_develop('slapos.recipe.template', test) testing.install_develop('slapos.recipe.template', test)
(lambda system, buildout, **kw: test.globs.update( (lambda system, buildout, **kw: test.globs.update(
run_buildout = lambda: print(system(buildout), end='') run_buildout = lambda *args: print(system(' '.join((buildout,) + args)),
end='')
))(**test.globs) ))(**test.globs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment