Enable dynamic creation of uwsgi pyargv option

Specifying hard-coded config files via the uwsgi pyargv option
caused failures when a file didn't exist.

This patch enables dynamic creation of the pyargv option. This
value is pushed onto the context for templated file generation
which is now supported as a subelement of an entry point as
well as a top level global option.

Change-Id: I1d0fae42b2e43fe8808fda3de83e122502233a4c
This commit is contained in:
Corey Bryant 2017-05-16 17:58:44 +00:00 committed by James Page
parent ed986bac6d
commit 44b532041f
3 changed files with 68 additions and 8 deletions

View File

@ -131,6 +131,7 @@ class OpenStackSnap(object):
def execute(self, argv):
'''Execute snap command building out configuration and log options'''
renderer = SnapFileRenderer()
utils = SnapUtils()
entry_point = self.configuration['entry_points'].get(argv[1])
@ -180,16 +181,56 @@ class OpenStackSnap(object):
cmd = ["{snap}/bin/uwsgi".format(**utils.snap_env)]
defaults = [d.format(**utils.snap_env) for d in DEFAULT_UWSGI_ARGS]
cmd.extend(defaults)
pyargv = []
uwsgi_dir = entry_point.get('uwsgi-dir')
if uwsgi_dir:
uwsgi_dir = uwsgi_dir.format(**utils.snap_env)
cmd.append(uwsgi_dir)
uwsgi_log = entry_point.get('uwsgi-log')
if uwsgi_log:
uwsgi_log = uwsgi_log.format(**utils.snap_env)
cmd.extend(['--logto', uwsgi_log])
for cfile in entry_point.get('config-files', []):
cfile = cfile.format(**utils.snap_env)
if os.path.exists(cfile):
pyargv.append('--config-file={}'.format(cfile))
else:
LOG.debug('Configuration file {} not found'
', skipping'.format(cfile))
for cdir in entry_point.get('config-dirs', []):
cdir = cdir.format(**utils.snap_env)
if os.path.exists(cdir):
pyargv.append('--config-dir={}'.format(cdir))
else:
LOG.debug('Configuration directory {} not found'
', skipping'.format(cdir))
log_file = entry_point.get('log-file')
if log_file:
log_file = log_file.format(**utils.snap_env)
cmd.extend(['--logto', log_file])
pyargv.append('--log-file={}'.format(log_file))
# NOTE(jamespage): Pass dynamically built pyargv into
# context for template generation.
snap_env = utils.snap_env
if pyargv:
snap_env['pyargv'] = ' '.join(pyargv)
for template in entry_point.get('templates', []):
target = entry_point['templates'][template]
target_file = target.format(**utils.snap_env)
utils.ensure_dir(target_file, is_file=True)
if not os.path.isfile(target_file):
LOG.debug('Rendering {} to {}'.format(template,
target_file))
with open(target_file, 'w') as tf:
os.fchmod(tf.fileno(), 0o640)
tf.write(renderer.render(template, snap_env))
elif cmd_type == NGINX_EP_TYPE:
cmd = ["{snap}/usr/sbin/nginx".format(**utils.snap_env)]

View File

@ -28,7 +28,14 @@ entry_points:
keystone-uwsgi:
type: uwsgi
uwsgi-dir: "/etc/uwsgi"
log-file: "/var/log/uwsgi/keystone.log"
uwsgi-log: "/var/log/uwsgi/keystone.log"
config-files:
- "/etc/keystone/keystone.conf"
config-dirs:
- "/etc/keystone/conf.d"
log-file: "/var/log/keystone/keystone.log"
templates:
"admin.ini.j2": "/etc/uwsgi/admin.ini"
keystone-nginx:
type: nginx
config-file: "/etc/nginx/keystone/nginx.conf"

View File

@ -51,9 +51,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
snap_utils.snap_env = MOCK_SNAP_ENV
snap_utils.drop_privileges.return_value = None
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config(self, mock_os, mock_utils):
def test_base_snap_config(self, mock_os, mock_utils,
mock_renderer):
'''Ensure wrapped binary called with full args list'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,
@ -69,9 +71,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
'--log-file=/var/log/nova/scheduler.log']
)
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config_no_logging(self, mock_os, mock_utils):
def test_base_snap_config_no_logging(self, mock_os, mock_utils,
mock_renderer):
'''Ensure wrapped binary called correctly with no logfile'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,
@ -88,9 +92,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
'db', 'sync']
)
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config_missing_entry_point(self, mock_os, mock_utils):
def test_base_snap_config_missing_entry_point(self, mock_os, mock_utils,
mock_renderer):
'''Ensure ValueError raised for missing entry_point'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,
@ -101,9 +107,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
['snap-openstack',
'nova-api'])
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config_uwsgi(self, mock_os, mock_utils):
def test_base_snap_config_uwsgi(self, mock_os, mock_utils,
mock_renderer):
'''Ensure wrapped binary of uwsgi called with correct arguments'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,
@ -119,9 +127,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
'--logto', '/var/log/uwsgi/keystone.log']
)
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config_nginx(self, mock_os, mock_utils):
def test_base_snap_config_nginx(self, mock_os, mock_utils,
mock_renderer):
'''Ensure wrapped binary of nginx called with correct arguments'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,
@ -135,9 +145,11 @@ class TestOpenStackSnapExecute(test_base.TestCase):
'daemon on; master_process on;']
)
@patch.object(base, 'SnapFileRenderer')
@patch('snap_openstack.base.SnapUtils')
@patch.object(base, 'os')
def test_base_snap_config_invalid_ep_type(self, mock_os, mock_utils):
def test_base_snap_config_invalid_ep_type(self, mock_os, mock_utils,
mock_renderer):
'''Ensure endpoint types are correctly validated'''
self.mock_snap_utils(mock_utils)
snap = base.OpenStackSnap(os.path.join(TEST_DIR,