charm-keystone/unit_tests/test_keystone_contexts.py
Billy Olsen 55274a7867 Install cron job to flush keystone tokens.
This change adds a cron job definition to flush the keystone tokens
once every hour. Without this, the keystone database grows unbounded,
which can be problematic in production environments.

This change introduces a new keystone-token-flush templated cron job,
which will run the keystone-manage token_flush command as the keystone
user once per hour. This change honors the use-syslog setting by
sending output of the command either to the keystone-token-flush.log
file or to the syslog using the logger exec.

Only the juju service leader will have the cron job active in order to
prevent multiple units from running the token_flush at the concurrently.

Change-Id: I21be3b23a8fe66b67fba0654ce498d62b3afc2ac
Closes-Bug: #1467832
2016-03-10 07:42:58 -07:00

181 lines
7.8 KiB
Python

import os
import keystone_context as context
from mock import patch, MagicMock
from test_utils import (
CharmTestCase
)
TO_PATCH = [
'config',
'determine_apache_port',
'determine_api_port',
'is_cert_provided_in_config',
]
class TestKeystoneContexts(CharmTestCase):
def setUp(self):
super(TestKeystoneContexts, self).setUp(context, TO_PATCH)
@patch.object(context, 'is_cert_provided_in_config')
@patch.object(context, 'mkdir')
@patch('keystone_utils.get_ca')
@patch('keystone_utils.ensure_permissions')
@patch('keystone_utils.determine_ports')
@patch('keystone_utils.is_ssl_cert_master')
@patch.object(context, 'log')
def test_apache_ssl_context_ssl_not_master(self,
mock_log,
mock_is_ssl_cert_master,
mock_determine_ports,
mock_ensure_permissions,
mock_get_ca,
mock_mkdir,
mock_cert_provided_in_config):
mock_cert_provided_in_config.return_value = False
mock_is_ssl_cert_master.return_value = False
context.ApacheSSLContext().configure_cert('foo')
context.ApacheSSLContext().configure_ca()
self.assertTrue(mock_mkdir.called)
self.assertTrue(mock_ensure_permissions.called)
self.assertFalse(mock_get_ca.called)
@patch('keystone_utils.determine_ports')
@patch('keystone_utils.is_ssl_cert_master')
@patch('charmhelpers.contrib.openstack.context.config')
@patch('charmhelpers.contrib.openstack.context.is_clustered')
@patch('charmhelpers.contrib.openstack.context.determine_apache_port')
@patch('charmhelpers.contrib.openstack.context.determine_api_port')
@patch('charmhelpers.contrib.openstack.context.unit_get')
@patch('charmhelpers.contrib.openstack.context.https')
def test_apache_ssl_context_service_enabled(self, mock_https,
mock_unit_get,
mock_determine_api_port,
mock_determine_apache_port,
mock_is_clustered,
mock_config,
mock_is_ssl_cert_master,
mock_determine_ports):
mock_is_ssl_cert_master.return_value = True
mock_https.return_value = True
mock_unit_get.return_value = '1.2.3.4'
mock_determine_api_port.return_value = '12'
mock_determine_apache_port.return_value = '34'
mock_is_clustered.return_value = False
mock_config.return_value = None
mock_determine_ports.return_value = ['12']
ctxt = context.ApacheSSLContext()
ctxt.enable_modules = MagicMock()
ctxt.configure_cert = MagicMock()
ctxt.configure_ca = MagicMock()
ctxt.canonical_names = MagicMock()
self.assertEquals(ctxt(), {'endpoints': [('1.2.3.4',
'1.2.3.4',
34, 12)],
'namespace': 'keystone',
'ext_ports': [34]})
self.assertTrue(mock_https.called)
mock_unit_get.assert_called_with('private-address')
@patch('keystone_utils.api_port')
@patch('charmhelpers.contrib.openstack.context.get_netmask_for_address')
@patch('charmhelpers.contrib.openstack.context.get_address_in_network')
@patch('charmhelpers.contrib.openstack.context.config')
@patch('charmhelpers.contrib.openstack.context.relation_ids')
@patch('charmhelpers.contrib.openstack.context.unit_get')
@patch('charmhelpers.contrib.openstack.context.related_units')
@patch('charmhelpers.contrib.openstack.context.relation_get')
@patch('charmhelpers.contrib.openstack.context.log')
@patch('charmhelpers.contrib.openstack.context.kv')
@patch('__builtin__.open')
def test_haproxy_context_service_enabled(
self, mock_open, mock_kv, mock_log, mock_relation_get,
mock_related_units, mock_unit_get, mock_relation_ids, mock_config,
mock_get_address_in_network, mock_get_netmask_for_address,
mock_api_port):
os.environ['JUJU_UNIT_NAME'] = 'keystone'
mock_relation_ids.return_value = ['identity-service:0', ]
mock_unit_get.return_value = '1.2.3.4'
mock_relation_get.return_value = '10.0.0.0'
mock_related_units.return_value = ['unit/0', ]
mock_config.return_value = None
mock_get_address_in_network.return_value = None
mock_get_netmask_for_address.return_value = '255.255.255.0'
self.determine_apache_port.return_value = '34'
mock_api_port.return_value = '12'
mock_kv().get.return_value = 'abcdefghijklmnopqrstuvwxyz123456'
ctxt = context.HAProxyContext()
self.maxDiff = None
self.assertEquals(
ctxt(),
{'listen_ports': {'admin_port': '12',
'public_port': '12'},
'local_host': '127.0.0.1',
'haproxy_host': '0.0.0.0',
'stat_port': '8888',
'stat_password': 'abcdefghijklmnopqrstuvwxyz123456',
'service_ports': {'admin-port': ['12', '34'],
'public-port': ['12', '34']},
'default_backend': '1.2.3.4',
'frontends': {'1.2.3.4': {
'network': '1.2.3.4/255.255.255.0',
'backends': {
'keystone': '1.2.3.4',
'unit-0': '10.0.0.0'
}
}}
}
)
@patch('charmhelpers.contrib.openstack.context.log')
@patch('charmhelpers.contrib.openstack.context.config')
@patch('charmhelpers.contrib.openstack.context.unit_get')
@patch('charmhelpers.contrib.openstack.context.is_clustered')
@patch('charmhelpers.contrib.network.ip.get_address_in_network')
def test_canonical_names_without_network_splits(self,
mock_get_address,
mock_is_clustered,
mock_unit_get,
mock_config,
mock_log):
NET_CONFIG = {'vip': '10.0.3.1 10.0.3.2',
'os-internal-network': None,
'os-admin-network': None,
'os-public-network': None}
mock_unit_get.return_value = '10.0.3.10'
mock_is_clustered.return_value = True
config = {}
config.update(NET_CONFIG)
mock_config.side_effect = lambda key: config[key]
apache = context.ApacheSSLContext()
apache.canonical_names()
msg = "Multiple networks configured but net_type" \
" is None (os-public-network)."
mock_log.assert_called_with(msg, level="WARNING")
@patch.object(context, 'config')
def test_keystone_logger_context(self, mock_config):
ctxt = context.KeystoneLoggingContext()
mock_config.return_value = None
self.assertEqual({'log_level': None}, ctxt())
@patch.object(context, 'is_elected_leader')
def test_token_flush_context(self, mock_is_elected_leader):
ctxt = context.TokenFlushContext()
mock_is_elected_leader.return_value = False
self.assertEqual({'token_flush': False}, ctxt())
mock_is_elected_leader.return_value = True
self.assertEqual({'token_flush': True}, ctxt())