Commit 6f7b3a31 by Alain Takoudjou

slapos.cookbook: add new recipe for python promises plugin script generation with eggs

This recipe will be used to generate promise in etc/plugin dir. It solve the problem of promise eggs
dependencies and allow to set custom parameter to use in promise.

The generated script will looks like:

    import sys
    sys.path[0:0] = [
      ...
    ]

    extra_config_dict = {
      'KEY': 'VALUE'
    }

    CONTENT

CONTENT is a python code, the expected content looks like:

    from namespace.module import RunPromise

then the promise section in buildout will be something like:

    [my-promise]
    recipe = slapos.cookbook:promise.plugin
    eggs =
      NAME
      ...
    output = OUTPUT
    content =
      from namespace.module import RunPromise

    config-KEY = VALUE
1 parent 8e7b2698
......@@ -150,6 +150,7 @@ setup(name=name,
'postgres.export = slapos.recipe.postgres.backup:ExportRecipe',
'postgres.import = slapos.recipe.postgres.backup:ImportRecipe',
'proactive = slapos.recipe.proactive:Recipe',
'promise.plugin= slapos.recipe.promise_plugin:Recipe',
'publish = slapos.recipe.publish:Recipe',
'publish.serialised = slapos.recipe.publish:Serialised',
'publish-early = slapos.recipe.publish_early:Recipe',
......
##############################################################################
#
# Copyright (c) 2018 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import logging, os, sys
import zc.buildout.easy_install
from slapos.recipe.librecipe import GenericBaseRecipe
script_template = '''# This script is auto generated by slapgrid, do not edit!
import sys
sys.path[0:0] = [
%(path)s
]
extra_config_dict = {
%(config)s
}
# We want to cleanup all imported modules from slapos namespace, because
# they will conflict with slapos.core.
# In fact as slapos.grid is already imported, the promise cannot reimport
# his own slapos.grid from an updated sys.path. Then all module imports which
# are not in slapos.core will fail.
#
# call reload(slapos) only solve a part of problem because not all modules
# will be reloaded, and some new modules won't be added.
# The solution is to delete all cached 'slapos' modules as well as all cached
# 'pkg_resources' modules which is responsible of namespace declaration.
# They will be re-imported again using the updated sys.path
for module in sys.modules.keys():
if 'slapos' in module or 'pkg_resources' in module:
del sys.modules[module]
import slapos.grid.promise
%(content)s
'''
class Recipe(GenericBaseRecipe):
_WORKING_SET_CACHE_NAME = "slapos.cookbook_pplugin_ws_cache"
def __init__(self, buildout, name, options):
buildout_section = buildout['buildout']
options['eggs-directory'] = buildout_section['eggs-directory']
options['develop-eggs-directory'] = buildout_section['develop-eggs-directory']
super(Recipe, self).__init__(buildout, name, options)
def _get_cache_storage(self):
"""Return a mapping where to store generated working sets.
from https://github.com/buildout/buildout/blob/master/zc.recipe.egg_/src/zc/recipe/egg/egg.py#L170
"""
cache_storage = getattr(
self.buildout,
self._WORKING_SET_CACHE_NAME,
None
)
if cache_storage is None:
cache_storage = {}
setattr(
self.buildout,
self._WORKING_SET_CACHE_NAME,
cache_storage
)
return cache_storage
def install(self):
develop_eggs_dir = self.options['develop-eggs-directory']
eggs_dir = self.options['eggs-directory']
egg_list = [
egg.strip()
for egg in self.options['eggs'].split('\n')
if egg.strip()
]
cache_storage = self._get_cache_storage()
cache_key = (
tuple(egg_list),
eggs_dir,
develop_eggs_dir,
)
if cache_key not in cache_storage:
working_set = zc.buildout.easy_install.working_set(
egg_list,
[develop_eggs_dir, eggs_dir]
)
cache_storage[cache_key] = working_set
else:
working_set = cache_storage[cache_key]
content = self.options['content'].strip()
output = self.options['output']
mode = self.options.get('mode', '0600')
path_list_string = ""
for dist in working_set:
path_list_string += ' "%s",\n' % dist.location
content_string = '\n'.join([line.lstrip() for line in content.split('\n')])
config_string = ""
for key in self.options:
if key.startswith('config-'):
config_string += " '%s': '%s',\n" % (key[7:], self.options[key])
option_dict = dict(path=path_list_string.strip(),
content=content_string,
config=config_string.strip())
with open(output, 'w') as f:
f.write(script_template % option_dict)
os.chmod(output, int(mode, 8))
return (output,)
update = install
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!