Skip to content

Commit

Permalink
Add support for setting cgi-environment vars
Browse files Browse the repository at this point in the history
This is needed so that we are able to tell Plone to run in HTTPS mode on
PaaS providers such as Heroku. Currently, it is achieved with the following
Ugly Hack™:
https://github.com/plone/heroku-buildpack-plone/blob/f22284cef9d790970d309c8c4591441d24b961ec/configure_zopeconf.py#L22
  • Loading branch information
zupo committed Apr 11, 2018
1 parent 20d6860 commit cc254c3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ New features:
- Added support for setting `instance-home` option.
[zupo]

- Added support for setting CGI environment variables.
[zupo]

Bug fixes:

- *add item here*
Expand Down
7 changes: 7 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ environment-vars
zope_i18n_allowed_languages en
zope_i18n_compile_mo_files true

cgi-environment-vars
Define arbitrary key-value pairs for use as CGI environment variables during
Zope's run cycle. Example::

cgi-environment-vars =
HTTPS ON

initialization
Specify some Python initialization code to include within the generated
``sitecustomize.py`` script (Buildout >= 1.5) or within the instance script
Expand Down
47 changes: 32 additions & 15 deletions src/plone/recipe/zope2instance/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ def indent(snippet, amount):
return "\n".join(ws + s if s else "" for s in snippet.split('\n'))


def handle_singleline_env_vars(vars_):
# if the vars are all given on one line we need to do some work
if not '\n' in vars_:
keys = []
values = []
env_vars = vars_.split()
# split out the odd and even items into keys, values
for var in env_vars:
if divmod(env_vars.index(var) + 1, 2)[1]:
keys.append(var)
else:
values.append(var)
env_vars = zip(keys, values)
return '\n'.join(
["%s %s" % (env_var[0], env_var[1]) for env_var in env_vars])
return vars_


class Recipe(Scripts):

def __init__(self, buildout, name, options):
Expand Down Expand Up @@ -229,21 +247,12 @@ def build_zope_conf(self):
ip_address = 'ip-address %s' % ip_address
environment_vars = options.get('environment-vars', '')
if environment_vars:
# if the vars are all given on one line we need to do some work
if not '\n' in environment_vars:
keys = []
values = []
env_vars = environment_vars.split()
# split out the odd and even items into keys, values
for var in env_vars:
if divmod(env_vars.index(var) + 1, 2)[1]:
keys.append(var)
else:
values.append(var)
env_vars = zip(keys, values)
environment_vars = '\n'.join(["%s %s" % (env_var[0], env_var[1])
for env_var in env_vars])
environment_vars = environment_template % environment_vars
environment_vars = environment_template % \
handle_singleline_env_vars(environment_vars)
cgi_environment_vars = options.get('cgi-environment-vars', '')
if cgi_environment_vars:
cgi_environment_vars = cgi_environment_template % \
handle_singleline_env_vars(cgi_environment_vars)

deprecation_warnings = options.get('deprecation-warnings', '')
if deprecation_warnings:
Expand Down Expand Up @@ -593,6 +602,7 @@ def is_rs_option(name):
pid_file = pid_file,
lock_file = lock_file,
environment_vars = environment_vars,
cgi_environment_vars = cgi_environment_vars,
deprecation_warnings = deprecation_warnings,
python_check_interval = python_check_interval,
enable_products = enable_products,
Expand Down Expand Up @@ -990,6 +1000,12 @@ def render_file_storage(self, file_storage, blob_storage,
</environment>
"""

cgi_environment_template = """
<cgi-environment>
%s
</cgi-environment>
"""

# The template used to build zope.conf
zope_conf_template="""\
%(imports_lines)s
Expand All @@ -1009,6 +1025,7 @@ def render_file_storage(self, file_storage, blob_storage,
%(ip_address)s
%(zserver_threads)s
%(environment_vars)s
%(cgi_environment_vars)s
%(deprecation_warnings)s
%(mailinglogger_import)s
Expand Down
38 changes: 38 additions & 0 deletions src/plone/recipe/zope2instance/tests/zope2instance.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,44 @@ Our environment variables should be set now::
>>> re.search(env_vars, zope_conf).group('vars')
'TZ US/Eastern\nTMP /var/tmp\nDISABLE_PTS True'

We can also specify CGI environment variables for Zope. This comes handy when
hosting on PaaS providers, such as Heroku, where we don't have a reverse-proxy
in front of Zope. For example, we can configure Zope to run in HTTPS mode::

>>> write('buildout.cfg',
... '''
... [buildout]
... parts = instance
... find-links = %(sample_buildout)s/eggs
...
... [instance]
... recipe = plone.recipe.zope2instance
... eggs =
... user = me:me
... cgi-environment-vars = HTTPS ON
... ''' % options)

Let's run it::

>>> print system(join('bin', 'buildout')),
Uninstalling instance.
Installing instance.
Generated script '...instance'.
Generated interpreter '.../parts/instance/bin/interpreter'.
...

Our CGI environment variables should be set now::

>>> instance = os.path.join(sample_buildout, 'parts', 'instance')
>>> zope_conf = open(os.path.join(instance, 'etc', 'zope.conf')).read()
>>> zope_conf = zope_conf.replace('\\', '/')
>>> print zope_conf
%define INSTANCEHOME .../sample-buildout/parts/instance
...
<cgi-environment>
HTTPS ON
</cgi-environment>
...

HTTP server
===========
Expand Down

0 comments on commit cc254c3

Please sign in to comment.