Use ApacheSSLContext to enable SSL object storage
Enable SSL object storage using ApacheSSLContext. Change-Id: Id044afc8c07696a5447eb9dc4836470203372090 Closes-Bug: #1690826 Closes-Bug: #1708464
This commit is contained in:
parent
30f7d5fec9
commit
2226518612
|
@ -41,6 +41,15 @@ from charmhelpers.contrib.network.ip import (
|
|||
from charmhelpers.contrib.storage.linux.ceph import CephConfContext
|
||||
|
||||
|
||||
class ApacheSSLContext(context.ApacheSSLContext):
|
||||
interfaces = ['https']
|
||||
service_namespace = 'ceph-radosgw'
|
||||
|
||||
def __call__(self):
|
||||
self.external_ports = [config('port')]
|
||||
return super(ApacheSSLContext, self).__call__()
|
||||
|
||||
|
||||
class HAProxyContext(context.HAProxyContext):
|
||||
|
||||
def __call__(self):
|
||||
|
@ -163,7 +172,7 @@ class MonContext(context.CephContext):
|
|||
if config('prefer-ipv6'):
|
||||
ensure_host_resolvable_v6(host)
|
||||
|
||||
port = determine_apache_port(config('port'), singlenode_mode=True)
|
||||
port = determine_api_port(config('port'), singlenode_mode=True)
|
||||
if config('prefer-ipv6'):
|
||||
port = "[::]:%s" % (port)
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ from charmhelpers.payload.execd import execd_preinstall
|
|||
from charmhelpers.core.host import (
|
||||
cmp_pkgrevno,
|
||||
is_container,
|
||||
service_reload,
|
||||
)
|
||||
from charmhelpers.contrib.network.ip import (
|
||||
get_relation_ip,
|
||||
|
@ -78,6 +79,7 @@ from utils import (
|
|||
services,
|
||||
assess_status,
|
||||
setup_keystone_certs,
|
||||
disable_unused_apache_sites,
|
||||
)
|
||||
from charmhelpers.contrib.charmsupport import nrpe
|
||||
from charmhelpers.contrib.hardening.harden import harden
|
||||
|
@ -96,11 +98,11 @@ PACKAGES = [
|
|||
# since python-keystoneclient does not pull in icehouse
|
||||
# version
|
||||
'radosgw',
|
||||
'apache2'
|
||||
]
|
||||
|
||||
APACHE_PACKAGES = [
|
||||
'libapache2-mod-fastcgi',
|
||||
'apache2',
|
||||
]
|
||||
|
||||
|
||||
|
@ -114,6 +116,7 @@ def install_packages():
|
|||
status_set('maintenance', 'Installing radosgw packages')
|
||||
apt_install(PACKAGES, fatal=True)
|
||||
apt_purge(APACHE_PACKAGES)
|
||||
disable_unused_apache_sites()
|
||||
|
||||
|
||||
@hooks.hook('install.real')
|
||||
|
@ -136,6 +139,7 @@ def install():
|
|||
@harden()
|
||||
def config_changed():
|
||||
install_packages()
|
||||
disable_unused_apache_sites()
|
||||
|
||||
if config('prefer-ipv6'):
|
||||
status_set('maintenance', 'configuring ipv6')
|
||||
|
@ -154,6 +158,7 @@ def config_changed():
|
|||
mon_relation(r_id, unit)
|
||||
|
||||
CONFIGS.write_all()
|
||||
configure_https()
|
||||
|
||||
update_nrpe_config()
|
||||
|
||||
|
@ -205,11 +210,11 @@ def identity_joined(relid=None):
|
|||
sys.exit(1)
|
||||
|
||||
port = config('port')
|
||||
admin_url = '%s:%i/swift' % (canonical_url(None, ADMIN), port)
|
||||
admin_url = '%s:%i/swift' % (canonical_url(CONFIGS, ADMIN), port)
|
||||
internal_url = '%s:%s/swift/v1' % \
|
||||
(canonical_url(None, INTERNAL), port)
|
||||
(canonical_url(CONFIGS, INTERNAL), port)
|
||||
public_url = '%s:%s/swift/v1' % \
|
||||
(canonical_url(None, PUBLIC), port)
|
||||
(canonical_url(CONFIGS, PUBLIC), port)
|
||||
relation_set(service='swift',
|
||||
region=config('region'),
|
||||
public_url=public_url, internal_url=internal_url,
|
||||
|
@ -217,12 +222,6 @@ def identity_joined(relid=None):
|
|||
requested_roles=config('operator-roles'),
|
||||
relation_id=relid)
|
||||
|
||||
if relid:
|
||||
for unit in related_units(relid):
|
||||
setup_keystone_certs(unit=unit, rid=relid)
|
||||
else:
|
||||
setup_keystone_certs()
|
||||
|
||||
|
||||
@hooks.hook('identity-service-relation-changed')
|
||||
@restart_on_change({'/etc/ceph/ceph.conf': ['radosgw']})
|
||||
|
@ -231,6 +230,7 @@ def identity_changed(relid=None):
|
|||
CONFIGS.write_all()
|
||||
if not is_unit_paused_set():
|
||||
restart()
|
||||
configure_https()
|
||||
|
||||
|
||||
@hooks.hook('cluster-relation-joined')
|
||||
|
@ -351,6 +351,32 @@ def update_nrpe_config():
|
|||
nrpe_setup.write()
|
||||
|
||||
|
||||
def configure_https():
|
||||
'''Enables SSL API Apache config if appropriate and kicks
|
||||
identity-service and image-service with any required
|
||||
updates
|
||||
'''
|
||||
CONFIGS.write_all()
|
||||
if 'https' in CONFIGS.complete_contexts():
|
||||
cmd = ['a2ensite', 'openstack_https_frontend']
|
||||
subprocess.check_call(cmd)
|
||||
else:
|
||||
cmd = ['a2dissite', 'openstack_https_frontend']
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
# The site is not yet enabled or
|
||||
# https is not configured
|
||||
pass
|
||||
|
||||
# TODO: improve this by checking if local CN certs are available
|
||||
# first then checking reload status (see LP #1433114).
|
||||
if not is_unit_paused_set():
|
||||
service_reload('apache2', restart_on_failure=True)
|
||||
|
||||
setup_keystone_certs(CONFIGS)
|
||||
|
||||
|
||||
@hooks.hook('update-status')
|
||||
@harden()
|
||||
def update_status():
|
||||
|
|
|
@ -28,6 +28,7 @@ from charmhelpers.core.hookenv import (
|
|||
INFO,
|
||||
relation_get,
|
||||
relation_ids,
|
||||
related_units,
|
||||
application_version_set,
|
||||
)
|
||||
from charmhelpers.contrib.network.ip import (
|
||||
|
@ -46,7 +47,10 @@ from charmhelpers.contrib.openstack.utils import (
|
|||
from charmhelpers.contrib.openstack.keystone import (
|
||||
format_endpoint,
|
||||
)
|
||||
from charmhelpers.contrib.hahelpers.cluster import get_hacluster_config
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
get_hacluster_config,
|
||||
https,
|
||||
)
|
||||
from charmhelpers.core.host import (
|
||||
cmp_pkgrevno,
|
||||
lsb_release,
|
||||
|
@ -104,6 +108,12 @@ CEPH_CONF = '/etc/ceph/ceph.conf'
|
|||
|
||||
VERSION_PACKAGE = 'radosgw'
|
||||
|
||||
UNUSED_APACHE_SITE_FILES = ["/etc/apache2/sites-available/000-default.conf"]
|
||||
APACHE_PORTS_FILE = "/etc/apache2/ports.conf"
|
||||
APACHE_SITE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
|
||||
APACHE_SITE_24_CONF = '/etc/apache2/sites-available/' \
|
||||
'openstack_https_frontend.conf'
|
||||
|
||||
BASE_RESOURCE_MAP = OrderedDict([
|
||||
(HAPROXY_CONF, {
|
||||
'contexts': [context.HAProxyContext(singlenode_mode=True),
|
||||
|
@ -114,6 +124,14 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||
'contexts': [ceph_radosgw_context.MonContext()],
|
||||
'services': ['radosgw'],
|
||||
}),
|
||||
(APACHE_SITE_CONF, {
|
||||
'contexts': [ceph_radosgw_context.ApacheSSLContext()],
|
||||
'services': ['apache2'],
|
||||
}),
|
||||
(APACHE_SITE_24_CONF, {
|
||||
'contexts': [ceph_radosgw_context.ApacheSSLContext()],
|
||||
'services': ['apache2'],
|
||||
}),
|
||||
])
|
||||
|
||||
|
||||
|
@ -131,6 +149,12 @@ def resource_map():
|
|||
These will be managed for a single hook execution.
|
||||
"""
|
||||
resource_map = deepcopy(BASE_RESOURCE_MAP)
|
||||
|
||||
if os.path.exists('/etc/apache2/conf-available'):
|
||||
resource_map.pop(APACHE_SITE_CONF)
|
||||
else:
|
||||
resource_map.pop(APACHE_SITE_24_CONF)
|
||||
|
||||
return resource_map
|
||||
|
||||
|
||||
|
@ -156,7 +180,10 @@ def services():
|
|||
_services = []
|
||||
for v in BASE_RESOURCE_MAP.values():
|
||||
_services.extend(v.get('services', []))
|
||||
return list(set(_services))
|
||||
_set_services = set(_services)
|
||||
if not https():
|
||||
_set_services.remove('apache2')
|
||||
return list(_set_services)
|
||||
|
||||
|
||||
def enable_pocket(pocket):
|
||||
|
@ -370,7 +397,9 @@ def get_ks_ca_cert(admin_token, auth_endpoint, certs_path):
|
|||
:param certs_path: Path to local certs store
|
||||
:returns: None
|
||||
"""
|
||||
ksclient = client.Client(token=admin_token, endpoint=auth_endpoint)
|
||||
|
||||
ksclient = keystoneclient.httpclient.HTTPClient(token=admin_token,
|
||||
endpoint=auth_endpoint)
|
||||
ca_cert = get_ks_cert(ksclient, auth_endpoint, 'ca')
|
||||
if ca_cert:
|
||||
try:
|
||||
|
@ -428,7 +457,7 @@ def get_ks_signing_cert(admin_token, auth_endpoint, certs_path):
|
|||
|
||||
|
||||
@defer_if_unavailable(['keystoneclient'])
|
||||
def setup_keystone_certs(unit=None, rid=None):
|
||||
def setup_keystone_certs(CONFIGS):
|
||||
"""
|
||||
Get CA and signing certs from Keystone used to decrypt revoked token list.
|
||||
|
||||
|
@ -440,14 +469,20 @@ def setup_keystone_certs(unit=None, rid=None):
|
|||
if not os.path.exists(certs_path):
|
||||
mkdir(certs_path)
|
||||
|
||||
rdata = relation_get(unit=unit, rid=rid)
|
||||
required = ['admin_token', 'auth_host', 'auth_port', 'api_version']
|
||||
settings = {key: rdata.get(key) for key in required}
|
||||
if not all(settings.values()):
|
||||
log("Missing relation settings ({}) - deferring cert setup".format(
|
||||
', '.join([k for k in settings if not settings[k]])),
|
||||
# Do not continue until identity-relation is complete
|
||||
if 'identity-service' not in CONFIGS.complete_contexts():
|
||||
log("Missing relation settings - deferring cert setup",
|
||||
level=DEBUG)
|
||||
return
|
||||
rdata = {}
|
||||
for relid in relation_ids('identity-service'):
|
||||
for unit in related_units(relid):
|
||||
rdata = relation_get(unit=unit, rid=relid)
|
||||
if rdata:
|
||||
break
|
||||
|
||||
required = ['admin_token', 'auth_host', 'auth_port', 'api_version']
|
||||
settings = {key: rdata.get(key) for key in required}
|
||||
|
||||
auth_protocol = rdata.get('auth_protocol', 'http')
|
||||
if is_ipv6(settings.get('auth_host')):
|
||||
|
@ -463,3 +498,21 @@ def setup_keystone_certs(unit=None, rid=None):
|
|||
get_ks_signing_cert(settings['admin_token'], auth_endpoint, certs_path)
|
||||
except KSCertSetupException as e:
|
||||
log("Keystone certs setup incomplete - {}".format(e), level=INFO)
|
||||
|
||||
|
||||
def disable_unused_apache_sites():
|
||||
"""Ensure that unused apache configurations are disabled to prevent them
|
||||
from conflicting with the charm-provided version.
|
||||
"""
|
||||
for apache_site_file in UNUSED_APACHE_SITE_FILES:
|
||||
apache_site = apache_site_file.split('/')[-1].split('.')[0]
|
||||
if os.path.exists(apache_site_file):
|
||||
try:
|
||||
# Try it cleanly
|
||||
subprocess.check_call(['a2dissite', apache_site])
|
||||
except subprocess.CalledProcessError:
|
||||
# Remove the file
|
||||
os.remove(apache_site_file)
|
||||
|
||||
with open(APACHE_PORTS_FILE, 'w') as ports:
|
||||
ports.write("")
|
||||
|
|
|
@ -29,6 +29,7 @@ TO_PATCH = [
|
|||
'cmp_pkgrevno',
|
||||
'socket',
|
||||
'unit_public_ip',
|
||||
'determine_api_port'
|
||||
]
|
||||
|
||||
|
||||
|
@ -54,6 +55,7 @@ class HAProxyContextTests(CharmTestCase):
|
|||
_haconfig.side_effect = self.test_config.get
|
||||
_harelation_ids.return_value = []
|
||||
haproxy_context = context.HAProxyContext()
|
||||
self.determine_api_port.return_value = 70
|
||||
expect = {
|
||||
'cephradosgw_bind_port': 70,
|
||||
'service_ports': {'cephradosgw-server': [80, 70]}
|
||||
|
@ -190,6 +192,7 @@ class MonContextTest(CharmTestCase):
|
|||
self.relation_get.side_effect = _relation_get
|
||||
self.relation_ids.return_value = ['mon:6']
|
||||
self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2']
|
||||
self.determine_api_port.return_value = 70
|
||||
expect = {
|
||||
'auth_supported': 'cephx',
|
||||
'hostname': 'testhost',
|
||||
|
@ -229,6 +232,7 @@ class MonContextTest(CharmTestCase):
|
|||
self.relation_get.side_effect = _relation_get
|
||||
self.relation_ids.return_value = ['mon:6']
|
||||
self.related_units.return_value = ['ceph-proxy/0']
|
||||
self.determine_api_port.return_value = 70
|
||||
expect = {
|
||||
'auth_supported': 'cephx',
|
||||
'hostname': 'testhost',
|
||||
|
@ -277,6 +281,7 @@ class MonContextTest(CharmTestCase):
|
|||
self.relation_get.side_effect = _relation_get
|
||||
self.relation_ids.return_value = ['mon:6']
|
||||
self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2']
|
||||
self.determine_api_port.return_value = 70
|
||||
expect = {
|
||||
'auth_supported': 'none',
|
||||
'hostname': 'testhost',
|
||||
|
@ -307,6 +312,7 @@ class MonContextTest(CharmTestCase):
|
|||
self.relation_get.side_effect = _relation_get
|
||||
self.relation_ids.return_value = ['mon:6']
|
||||
self.related_units.return_value = ['ceph/0', 'ceph/1', 'ceph/2']
|
||||
self.determine_api_port.return_value = 70
|
||||
expect = {
|
||||
'auth_supported': 'cephx',
|
||||
'hostname': 'testhost',
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
|
||||
from mock import (
|
||||
call,
|
||||
patch,
|
||||
|
@ -29,6 +27,7 @@ TO_PATCH = [
|
|||
'application_version_set',
|
||||
'get_upstream_version',
|
||||
'format_endpoint',
|
||||
'https',
|
||||
]
|
||||
|
||||
|
||||
|
@ -90,8 +89,11 @@ class CephRadosGWUtilTests(CharmTestCase):
|
|||
# ports=None whilst port checks are disabled.
|
||||
f.assert_called_once_with('assessor', services='s1', ports=None)
|
||||
|
||||
@patch.object(utils, 'related_units')
|
||||
@patch.object(utils, 'relation_ids')
|
||||
@patch.dict('sys.modules', {'requests': MagicMock(),
|
||||
'keystoneclient': MagicMock()})
|
||||
'keystoneclient': MagicMock(),
|
||||
'httpclient': MagicMock()})
|
||||
@patch.object(utils, 'is_ipv6', lambda addr: False)
|
||||
@patch.object(utils, 'get_ks_signing_cert')
|
||||
@patch.object(utils, 'get_ks_ca_cert')
|
||||
|
@ -99,93 +101,71 @@ class CephRadosGWUtilTests(CharmTestCase):
|
|||
@patch.object(utils, 'mkdir')
|
||||
def test_setup_keystone_certs(self, mock_mkdir, mock_relation_get,
|
||||
mock_get_ks_ca_cert,
|
||||
mock_get_ks_signing_cert):
|
||||
mock_get_ks_signing_cert,
|
||||
mock_relation_ids, mock_related_units):
|
||||
auth_host = 'foo/bar'
|
||||
auth_port = 80
|
||||
admin_token = '666'
|
||||
auth_url = 'http://%s:%s/v2.0' % (auth_host, auth_port)
|
||||
self.format_endpoint.return_value = auth_url
|
||||
configs = MagicMock()
|
||||
configs.complete_contexts.return_value = ['identity-service']
|
||||
mock_relation_ids.return_value = ['identity-service:5']
|
||||
mock_related_units.return_value = ['keystone/1']
|
||||
mock_relation_get.return_value = {'auth_host': auth_host,
|
||||
'auth_port': auth_port,
|
||||
'admin_token': admin_token,
|
||||
'api_version': '2'}
|
||||
utils.setup_keystone_certs()
|
||||
utils.setup_keystone_certs(configs)
|
||||
mock_get_ks_signing_cert.assert_has_calls([call(admin_token, auth_url,
|
||||
'/var/lib/ceph/nss')])
|
||||
mock_get_ks_ca_cert.assert_has_calls([call(admin_token, auth_url,
|
||||
'/var/lib/ceph/nss')])
|
||||
|
||||
def test_get_ks_signing_cert(self):
|
||||
@patch.object(utils, 'get_ks_cert')
|
||||
@patch.object(utils.subprocess, 'Popen')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def test_get_ks_signing_cert(self, mock_check_output, mock_Popen,
|
||||
mock_get_ks_cert):
|
||||
auth_host = 'foo/bar'
|
||||
auth_port = 80
|
||||
admin_token = '666'
|
||||
auth_url = 'http://%s:%s/v2.0' % (auth_host, auth_port)
|
||||
|
||||
mock_ksclient = MagicMock
|
||||
m = mock_open()
|
||||
with patch.dict('sys.modules',
|
||||
{'requests': MagicMock(),
|
||||
'keystoneclient': mock_ksclient,
|
||||
'keystoneclient.exceptions': MagicMock(),
|
||||
'keystoneclient.exceptions.ConnectionRefused':
|
||||
MagicMock(),
|
||||
'keystoneclient.exceptions.Forbidden': MagicMock(),
|
||||
'keystoneclient.v2_0': MagicMock(),
|
||||
'keystoneclient.v2_0.client': MagicMock()}):
|
||||
# Reimport
|
||||
del sys.modules['utils']
|
||||
import utils
|
||||
with patch.object(utils, 'subprocess') as mock_subprocess:
|
||||
with patch.object(utils, 'open', m, create=True):
|
||||
mock_certificates = MagicMock()
|
||||
mock_ksclient.certificates = mock_certificates
|
||||
mock_certificates.get_signing_certificate.return_value = \
|
||||
'signing_cert_data'
|
||||
utils.get_ks_signing_cert(admin_token, auth_url,
|
||||
'/foo/bar')
|
||||
mock_certificates.get_signing_certificate.return_value = \
|
||||
None
|
||||
self.assertRaises(utils.KSCertSetupException,
|
||||
utils.get_ks_signing_cert, admin_token,
|
||||
auth_url, '/foo/bar')
|
||||
with patch.object(utils, 'open', m, create=True):
|
||||
|
||||
c = ['openssl', 'x509', '-in',
|
||||
'/foo/bar/signing_certificate.pem',
|
||||
'-pubkey']
|
||||
mock_subprocess.check_output.assert_called_with(c)
|
||||
mock_get_ks_cert.return_value = 'signing_cert_data'
|
||||
utils.get_ks_signing_cert(admin_token, auth_url, '/foo/bar')
|
||||
|
||||
def test_get_ks_ca_cert(self):
|
||||
mock_get_ks_cert.return_value = None
|
||||
with self.assertRaises(utils.KSCertSetupException):
|
||||
utils.get_ks_signing_cert(admin_token, auth_url, '/foo/bar')
|
||||
|
||||
c = ['openssl', 'x509', '-in',
|
||||
'/foo/bar/signing_certificate.pem',
|
||||
'-pubkey']
|
||||
mock_check_output.assert_called_with(c)
|
||||
|
||||
@patch.object(utils, 'get_ks_cert')
|
||||
@patch.object(utils.subprocess, 'Popen')
|
||||
@patch.object(utils.subprocess, 'check_output')
|
||||
def test_get_ks_ca_cert(self, mock_check_output, mock_Popen,
|
||||
mock_get_ks_cert):
|
||||
auth_host = 'foo/bar'
|
||||
auth_port = 80
|
||||
admin_token = '666'
|
||||
auth_url = 'http://%s:%s/v2.0' % (auth_host, auth_port)
|
||||
|
||||
mock_ksclient = MagicMock
|
||||
m = mock_open()
|
||||
with patch.dict('sys.modules',
|
||||
{'requests': MagicMock(),
|
||||
'keystoneclient': mock_ksclient,
|
||||
'keystoneclient.exceptions': MagicMock(),
|
||||
'keystoneclient.exceptions.ConnectionRefused':
|
||||
MagicMock(),
|
||||
'keystoneclient.exceptions.Forbidden': MagicMock(),
|
||||
'keystoneclient.v2_0': MagicMock(),
|
||||
'keystoneclient.v2_0.client': MagicMock()}):
|
||||
# Reimport
|
||||
del sys.modules['utils']
|
||||
import utils
|
||||
with patch.object(utils, 'subprocess') as mock_subprocess:
|
||||
with patch.object(utils, 'open', m, create=True):
|
||||
mock_certificates = MagicMock()
|
||||
mock_ksclient.certificates = mock_certificates
|
||||
mock_certificates.get_ca_certificate.return_value = \
|
||||
'ca_cert_data'
|
||||
utils.get_ks_ca_cert(admin_token, auth_url, '/foo/bar')
|
||||
mock_certificates.get_ca_certificate.return_value = None
|
||||
self.assertRaises(utils.KSCertSetupException,
|
||||
utils.get_ks_ca_cert, admin_token,
|
||||
auth_url, '/foo/bar')
|
||||
with patch.object(utils, 'open', m, create=True):
|
||||
mock_get_ks_cert.return_value = 'ca_cert_data'
|
||||
utils.get_ks_ca_cert(admin_token, auth_url, '/foo/bar')
|
||||
|
||||
c = ['openssl', 'x509', '-in', '/foo/bar/ca.pem',
|
||||
'-pubkey']
|
||||
mock_subprocess.check_output.assert_called_with(c)
|
||||
mock_get_ks_cert.return_value = None
|
||||
with self.assertRaises(utils.KSCertSetupException):
|
||||
utils.get_ks_ca_cert(admin_token, auth_url, '/foo/bar')
|
||||
|
||||
c = ['openssl', 'x509', '-in', '/foo/bar/ca.pem',
|
||||
'-pubkey']
|
||||
mock_check_output.assert_called_with(c)
|
||||
|
|
|
@ -53,6 +53,9 @@ TO_PATCH = [
|
|||
'get_hacluster_config',
|
||||
'update_dns_ha_resource_params',
|
||||
'get_relation_ip',
|
||||
'disable_unused_apache_sites',
|
||||
'service_reload',
|
||||
'setup_keystone_certs',
|
||||
]
|
||||
|
||||
|
||||
|
@ -69,8 +72,7 @@ class CephRadosGWTests(CharmTestCase):
|
|||
ceph_hooks.install_packages()
|
||||
self.add_source.assert_called_with('distro', 'secretkey')
|
||||
self.assertTrue(self.apt_update.called)
|
||||
self.apt_purge.assert_called_with(['libapache2-mod-fastcgi',
|
||||
'apache2'])
|
||||
self.apt_purge.assert_called_with(['libapache2-mod-fastcgi'])
|
||||
|
||||
def test_install(self):
|
||||
_install_packages = self.patch('install_packages')
|
||||
|
@ -144,15 +146,12 @@ class CephRadosGWTests(CharmTestCase):
|
|||
cmd = ['service', 'radosgw', 'restart']
|
||||
self.subprocess.call.assert_called_with(cmd)
|
||||
|
||||
@patch.object(ceph_hooks, 'setup_keystone_certs')
|
||||
@patch('charmhelpers.contrib.openstack.ip.service_name',
|
||||
lambda *args: 'ceph-radosgw')
|
||||
@patch('charmhelpers.contrib.openstack.ip.config')
|
||||
def test_identity_joined_early_version(self, _config,
|
||||
mock_setup_keystone_certs):
|
||||
def test_identity_joined_early_version(self, _config):
|
||||
self.cmp_pkgrevno.return_value = -1
|
||||
ceph_hooks.identity_joined()
|
||||
self.assertTrue(mock_setup_keystone_certs.called)
|
||||
self.sys.exit.assert_called_with(1)
|
||||
|
||||
@patch('charmhelpers.contrib.openstack.ip.service_name',
|
||||
|
|
Loading…
Reference in New Issue