Refactor test utils to help testing in other aso charms
This commit is contained in:
parent
0547709b4b
commit
8d556b6a7b
208
advanced_sunbeam_openstack/test_utils.py
Normal file
208
advanced_sunbeam_openstack/test_utils.py
Normal file
@ -0,0 +1,208 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
import io
|
||||
import json
|
||||
from mock import patch
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
sys.path.append('lib') # noqa
|
||||
sys.path.append('src') # noqa
|
||||
|
||||
from ops import framework, model
|
||||
|
||||
from ops.testing import Harness, _TestingModelBackend, _TestingPebbleClient
|
||||
|
||||
|
||||
class CharmTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self, obj, patches):
|
||||
super().setUp()
|
||||
self.patches = patches
|
||||
self.obj = obj
|
||||
self.patch_all()
|
||||
|
||||
def patch(self, method):
|
||||
_m = patch.object(self.obj, method)
|
||||
mock = _m.start()
|
||||
self.addCleanup(_m.stop)
|
||||
return mock
|
||||
|
||||
def patch_obj(self, obj, method):
|
||||
_m = patch.object(obj, method)
|
||||
mock = _m.start()
|
||||
self.addCleanup(_m.stop)
|
||||
return mock
|
||||
|
||||
def patch_all(self):
|
||||
for method in self.patches:
|
||||
setattr(self, method, self.patch(method))
|
||||
|
||||
|
||||
def add_base_amqp_relation(harness):
|
||||
rel_id = harness.add_relation('amqp', 'rabbitmq')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'rabbitmq/0')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'rabbitmq/0')
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'rabbitmq/0',
|
||||
{'ingress-address': '10.0.0.13'})
|
||||
return rel_id
|
||||
|
||||
|
||||
def add_amqp_relation_credentials(harness, rel_id):
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'rabbitmq',
|
||||
{
|
||||
'hostname': 'rabbithost1.local',
|
||||
'password': 'rabbit.pass'})
|
||||
|
||||
|
||||
def add_base_identity_service_relation(harness):
|
||||
rel_id = harness.add_relation('identity-service', 'keystone')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'keystone/0')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'keystone/0')
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'keystone/0',
|
||||
{'ingress-address': '10.0.0.33'})
|
||||
return rel_id
|
||||
|
||||
|
||||
def add_identity_service_relation_response(harness, rel_id):
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'keystone',
|
||||
{
|
||||
'admin-domain-id': 'admindomid1',
|
||||
'admin-project-id': 'adminprojid1',
|
||||
'admin-user-id': 'adminuserid1',
|
||||
'api-version': '3',
|
||||
'auth-host': 'keystone.local',
|
||||
'auth-port': '12345',
|
||||
'auth-protocol': 'http',
|
||||
'internal-host': 'keystone.internal',
|
||||
'internal-port': '5000',
|
||||
'internal-protocol': 'http',
|
||||
'service-domain': 'servicedom',
|
||||
'service-domain_id': 'svcdomid1',
|
||||
'service-host': 'keystone.service',
|
||||
'service-password': 'svcpass1',
|
||||
'service-port': '5000',
|
||||
'service-protocol': 'http',
|
||||
'service-project': 'svcproj1',
|
||||
'service-project-id': 'svcprojid1',
|
||||
'service-username': 'svcuser1'})
|
||||
|
||||
|
||||
def add_base_db_relation(harness):
|
||||
rel_id = harness.add_relation('my-service-db', 'mysql')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'mysql/0')
|
||||
harness.add_relation_unit(
|
||||
rel_id,
|
||||
'mysql/0')
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'mysql/0',
|
||||
{'ingress-address': '10.0.0.3'})
|
||||
return rel_id
|
||||
|
||||
|
||||
def add_db_relation_credentials(harness, rel_id):
|
||||
harness.update_relation_data(
|
||||
rel_id,
|
||||
'mysql',
|
||||
{
|
||||
'databases': json.dumps(['db1']),
|
||||
'data': json.dumps({
|
||||
'credentials': {
|
||||
'username': 'foo',
|
||||
'password': 'hardpassword',
|
||||
'address': '10.0.0.10'}})})
|
||||
|
||||
|
||||
def add_api_relations(harness):
|
||||
add_db_relation_credentials(
|
||||
harness,
|
||||
add_base_db_relation(harness))
|
||||
add_amqp_relation_credentials(
|
||||
harness,
|
||||
add_base_amqp_relation(harness))
|
||||
add_identity_service_relation_response(
|
||||
harness,
|
||||
add_base_identity_service_relation(harness))
|
||||
|
||||
|
||||
def get_harness(charm_class, charm_meta, container_calls):
|
||||
|
||||
class _OSTestingPebbleClient(_TestingPebbleClient):
|
||||
|
||||
def push(
|
||||
self, path, source, *,
|
||||
encoding='utf-8', make_dirs=False, permissions=None,
|
||||
user_id=None, user=None, group_id=None, group=None):
|
||||
container_calls['push'][path] = {
|
||||
'source': source,
|
||||
'permissions': permissions,
|
||||
'user': user,
|
||||
'group': group}
|
||||
|
||||
def pull(self, path, *, encoding='utf-8'):
|
||||
container_calls['pull'].append(path)
|
||||
reader = io.StringIO("0")
|
||||
return reader
|
||||
|
||||
def remove_path(self, path, *, recursive=False):
|
||||
container_calls['remove_path'].append(path)
|
||||
|
||||
class _OSTestingModelBackend(_TestingModelBackend):
|
||||
|
||||
def get_pebble(self, socket_path: str):
|
||||
client = self._pebble_clients.get(socket_path, None)
|
||||
if client is None:
|
||||
client = _OSTestingPebbleClient(self)
|
||||
self._pebble_clients[socket_path] = client
|
||||
return client
|
||||
|
||||
harness = Harness(
|
||||
charm_class,
|
||||
meta=charm_meta,
|
||||
)
|
||||
harness._backend = _OSTestingModelBackend(
|
||||
harness._unit_name, harness._meta)
|
||||
harness._model = model.Model(
|
||||
harness._meta,
|
||||
harness._backend)
|
||||
harness._framework = framework.Framework(
|
||||
":memory:",
|
||||
harness._charm_dir,
|
||||
harness._meta,
|
||||
harness._model)
|
||||
# END Workaround
|
||||
return harness
|
199
unit_tests/test_charms.py
Normal file
199
unit_tests/test_charms.py
Normal file
@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2020 Canonical Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import sys
|
||||
|
||||
sys.path.append('lib') # noqa
|
||||
sys.path.append('src') # noqa
|
||||
|
||||
import advanced_sunbeam_openstack.charm as sunbeam_charm
|
||||
|
||||
CHARM_CONFIG = {
|
||||
'region': 'RegionOne',
|
||||
'debug': 'true'}
|
||||
|
||||
CHARM_METADATA = '''
|
||||
name: my-service
|
||||
version: 3
|
||||
bases:
|
||||
- name: ubuntu
|
||||
channel: 20.04/stable
|
||||
tags:
|
||||
- openstack
|
||||
- identity
|
||||
- misc
|
||||
|
||||
subordinate: false
|
||||
|
||||
containers:
|
||||
my-service:
|
||||
resource: mysvc-image
|
||||
mounts:
|
||||
- storage: db
|
||||
location: /var/lib/mysvc
|
||||
|
||||
storage:
|
||||
logs:
|
||||
type: filesystem
|
||||
db:
|
||||
type: filesystem
|
||||
|
||||
resources:
|
||||
mysvc-image:
|
||||
type: oci-image
|
||||
'''
|
||||
|
||||
API_CHARM_METADATA = '''
|
||||
name: my-service
|
||||
version: 3
|
||||
bases:
|
||||
- name: ubuntu
|
||||
channel: 20.04/stable
|
||||
tags:
|
||||
- openstack
|
||||
- identity
|
||||
- misc
|
||||
|
||||
subordinate: false
|
||||
|
||||
requires:
|
||||
my-service-db:
|
||||
interface: mysql_datastore
|
||||
limit: 1
|
||||
ingress:
|
||||
interface: ingress
|
||||
amqp:
|
||||
interface: rabbitmq
|
||||
identity-service:
|
||||
interface: keystone
|
||||
|
||||
peers:
|
||||
peers:
|
||||
interface: mysvc-peer
|
||||
|
||||
containers:
|
||||
my-service:
|
||||
resource: mysvc-image
|
||||
mounts:
|
||||
- storage: db
|
||||
location: /var/lib/mysvc
|
||||
|
||||
storage:
|
||||
logs:
|
||||
type: filesystem
|
||||
db:
|
||||
type: filesystem
|
||||
|
||||
resources:
|
||||
mysvc-image:
|
||||
type: oci-image
|
||||
'''
|
||||
|
||||
|
||||
class MyCharm(sunbeam_charm.OSBaseOperatorCharm):
|
||||
|
||||
openstack_release = 'diablo'
|
||||
service_name = 'my-service'
|
||||
|
||||
def __init__(self, framework):
|
||||
self.seen_events = []
|
||||
self.render_calls = []
|
||||
self._template_dir = self._setup_templates()
|
||||
super().__init__(framework)
|
||||
|
||||
def _log_event(self, event):
|
||||
self.seen_events.append(type(event).__name__)
|
||||
|
||||
def _on_service_pebble_ready(self, event):
|
||||
super()._on_service_pebble_ready(event)
|
||||
self._log_event(event)
|
||||
|
||||
def _on_config_changed(self, event):
|
||||
self._log_event(event)
|
||||
|
||||
def configure_charm(self, event):
|
||||
super().configure_charm(event)
|
||||
self._log_event(event)
|
||||
|
||||
@property
|
||||
def public_ingress_port(self):
|
||||
return 789
|
||||
|
||||
def _setup_templates(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
_template_dir = f'{tmpdir}/templates'
|
||||
os.mkdir(_template_dir)
|
||||
with open(f'{_template_dir}/my-service.conf.j2', 'w') as f:
|
||||
f.write("")
|
||||
return _template_dir
|
||||
|
||||
@property
|
||||
def template_dir(self):
|
||||
return self._template_dir
|
||||
|
||||
|
||||
TEMPLATE_CONTENTS = """
|
||||
{{ wsgi_config.wsgi_admin_script }}
|
||||
{{ my_service_db.database_password }}
|
||||
{{ options.debug }}
|
||||
{{ amqp.transport_url }}
|
||||
{{ amqp.hostname }}
|
||||
{{ identity_service.service_password }}
|
||||
"""
|
||||
|
||||
|
||||
class MyAPICharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
openstack_release = 'diablo'
|
||||
service_name = 'my-service'
|
||||
wsgi_admin_script = '/bin/wsgi_admin'
|
||||
wsgi_public_script = '/bin/wsgi_public'
|
||||
|
||||
def __init__(self, framework):
|
||||
self.seen_events = []
|
||||
self.render_calls = []
|
||||
self._template_dir = self._setup_templates()
|
||||
super().__init__(framework)
|
||||
|
||||
def _setup_templates(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
_template_dir = f'{tmpdir}/templates'
|
||||
os.mkdir(_template_dir)
|
||||
with open(f'{_template_dir}/my-service.conf.j2', 'w') as f:
|
||||
f.write(TEMPLATE_CONTENTS)
|
||||
with open(f'{_template_dir}/wsgi-my-service.conf.j2', 'w') as f:
|
||||
f.write(TEMPLATE_CONTENTS)
|
||||
return _template_dir
|
||||
|
||||
def _log_event(self, event):
|
||||
self.seen_events.append(type(event).__name__)
|
||||
|
||||
def _on_service_pebble_ready(self, event):
|
||||
super()._on_service_pebble_ready(event)
|
||||
self._log_event(event)
|
||||
|
||||
def _on_config_changed(self, event):
|
||||
self._log_event(event)
|
||||
|
||||
@property
|
||||
def default_public_ingress_port(self):
|
||||
return 789
|
||||
|
||||
@property
|
||||
def template_dir(self):
|
||||
return self._template_dir
|
@ -15,171 +15,34 @@
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from mock import ANY, patch
|
||||
import unittest
|
||||
from mock import patch
|
||||
import sys
|
||||
|
||||
sys.path.append('lib') # noqa
|
||||
sys.path.append('src') # noqa
|
||||
|
||||
from ops import framework, model
|
||||
|
||||
from ops.testing import Harness, _TestingModelBackend, _TestingPebbleClient
|
||||
|
||||
import advanced_sunbeam_openstack.charm as sunbeam_charm
|
||||
|
||||
CHARM_CONFIG = {
|
||||
'region': 'RegionOne',
|
||||
'debug': 'true'}
|
||||
|
||||
CHARM_METADATA = '''
|
||||
name: my-service
|
||||
version: 3
|
||||
bases:
|
||||
- name: ubuntu
|
||||
channel: 20.04/stable
|
||||
tags:
|
||||
- openstack
|
||||
- identity
|
||||
- misc
|
||||
|
||||
subordinate: false
|
||||
|
||||
containers:
|
||||
my-service:
|
||||
resource: mysvc-image
|
||||
mounts:
|
||||
- storage: db
|
||||
location: /var/lib/mysvc
|
||||
|
||||
storage:
|
||||
logs:
|
||||
type: filesystem
|
||||
db:
|
||||
type: filesystem
|
||||
|
||||
resources:
|
||||
mysvc-image:
|
||||
type: oci-image
|
||||
'''
|
||||
|
||||
API_CHARM_METADATA = '''
|
||||
name: my-service
|
||||
version: 3
|
||||
bases:
|
||||
- name: ubuntu
|
||||
channel: 20.04/stable
|
||||
tags:
|
||||
- openstack
|
||||
- identity
|
||||
- misc
|
||||
|
||||
subordinate: false
|
||||
|
||||
requires:
|
||||
my-service-db:
|
||||
interface: mysql_datastore
|
||||
limit: 1
|
||||
ingress:
|
||||
interface: ingress
|
||||
amqp:
|
||||
interface: rabbitmq
|
||||
identity-service:
|
||||
interface: keystone
|
||||
|
||||
peers:
|
||||
peers:
|
||||
interface: mysvc-peer
|
||||
|
||||
containers:
|
||||
my-service:
|
||||
resource: mysvc-image
|
||||
mounts:
|
||||
- storage: db
|
||||
location: /var/lib/mysvc
|
||||
|
||||
storage:
|
||||
logs:
|
||||
type: filesystem
|
||||
db:
|
||||
type: filesystem
|
||||
|
||||
resources:
|
||||
mysvc-image:
|
||||
type: oci-image
|
||||
'''
|
||||
import advanced_sunbeam_openstack.test_utils as test_utils
|
||||
from . import test_charms
|
||||
|
||||
|
||||
class CharmTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self, obj, patches):
|
||||
super().setUp()
|
||||
self.patches = patches
|
||||
self.obj = obj
|
||||
self.patch_all()
|
||||
|
||||
def patch(self, method):
|
||||
_m = patch.object(self.obj, method)
|
||||
mock = _m.start()
|
||||
self.addCleanup(_m.stop)
|
||||
return mock
|
||||
|
||||
def patch_obj(self, obj, method):
|
||||
_m = patch.object(obj, method)
|
||||
mock = _m.start()
|
||||
self.addCleanup(_m.stop)
|
||||
return mock
|
||||
|
||||
def patch_all(self):
|
||||
for method in self.patches:
|
||||
setattr(self, method, self.patch(method))
|
||||
|
||||
|
||||
class MyCharm(sunbeam_charm.OSBaseOperatorCharm):
|
||||
|
||||
openstack_release = 'diablo'
|
||||
service_name = 'my-service'
|
||||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
self.seen_events = []
|
||||
self.render_calls = []
|
||||
|
||||
def _log_event(self, event):
|
||||
self.seen_events.append(type(event).__name__)
|
||||
|
||||
def _on_service_pebble_ready(self, event):
|
||||
super()._on_service_pebble_ready(event)
|
||||
self._log_event(event)
|
||||
|
||||
def _on_config_changed(self, event):
|
||||
self._log_event(event)
|
||||
|
||||
def configure_charm(self, event):
|
||||
super().configure_charm(event)
|
||||
self._log_event(event)
|
||||
|
||||
@property
|
||||
def public_ingress_port(self):
|
||||
return 789
|
||||
|
||||
|
||||
class TestOSBaseOperatorCharm(CharmTestCase):
|
||||
class TestOSBaseOperatorCharm(test_utils.CharmTestCase):
|
||||
|
||||
PATCHES = [
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
self.container_calls = {
|
||||
'push': {},
|
||||
'pull': [],
|
||||
'remove_path': []}
|
||||
super().setUp(sunbeam_charm, self.PATCHES)
|
||||
self.harness = Harness(
|
||||
MyCharm,
|
||||
meta=CHARM_METADATA
|
||||
)
|
||||
self.harness.update_config(CHARM_CONFIG)
|
||||
self.harness = test_utils.get_harness(
|
||||
test_charms.MyCharm,
|
||||
test_charms.CHARM_METADATA,
|
||||
self.container_calls)
|
||||
self.harness.update_config(test_charms.CHARM_CONFIG)
|
||||
self.harness.begin()
|
||||
self.addCleanup(self.harness.cleanup)
|
||||
|
||||
@ -188,21 +51,16 @@ class TestOSBaseOperatorCharm(CharmTestCase):
|
||||
# Emit the PebbleReadyEvent
|
||||
self.harness.charm.on.my_service_pebble_ready.emit(container)
|
||||
|
||||
@patch('advanced_sunbeam_openstack.templating.sidecar_config_render')
|
||||
def test_pebble_ready_handler(self, _renderer):
|
||||
def test_pebble_ready_handler(self):
|
||||
self.assertEqual(self.harness.charm.seen_events, [])
|
||||
self.set_pebble_ready()
|
||||
self.assertEqual(self.harness.charm.seen_events, ['PebbleReadyEvent'])
|
||||
|
||||
@patch('advanced_sunbeam_openstack.templating.sidecar_config_render')
|
||||
def test_write_config(self, _renderer):
|
||||
def test_write_config(self):
|
||||
self.set_pebble_ready()
|
||||
_renderer.assert_called_once_with(
|
||||
[self.harness.model.unit.get_container("my-service")],
|
||||
[],
|
||||
'src/templates',
|
||||
'diablo',
|
||||
ANY)
|
||||
self.assertEqual(
|
||||
self.container_calls['push'],
|
||||
{})
|
||||
|
||||
def test_handler_prefix(self):
|
||||
self.assertEqual(
|
||||
@ -214,229 +72,39 @@ class TestOSBaseOperatorCharm(CharmTestCase):
|
||||
self.harness.charm.container_names,
|
||||
['my-service'])
|
||||
|
||||
def test_template_dir(self):
|
||||
self.assertEqual(
|
||||
self.harness.charm.template_dir,
|
||||
'src/templates')
|
||||
|
||||
def test_relation_handlers_ready(self):
|
||||
self.assertTrue(
|
||||
self.harness.charm.relation_handlers_ready())
|
||||
|
||||
TEMPLATE_CONTENTS = """
|
||||
{{ wsgi_config.wsgi_admin_script }}
|
||||
{{ my_service_db.database_password }}
|
||||
{{ options.debug }}
|
||||
{{ amqp.transport_url }}
|
||||
{{ amqp.hostname }}
|
||||
{{ identity_service.service_password }}
|
||||
"""
|
||||
|
||||
|
||||
class MyAPICharm(sunbeam_charm.OSBaseOperatorAPICharm):
|
||||
openstack_release = 'diablo'
|
||||
service_name = 'my-service'
|
||||
wsgi_admin_script = '/bin/wsgi_admin'
|
||||
wsgi_public_script = '/bin/wsgi_public'
|
||||
|
||||
def __init__(self, framework):
|
||||
self.seen_events = []
|
||||
self.render_calls = []
|
||||
self._template_dir = self._setup_templates()
|
||||
super().__init__(framework)
|
||||
|
||||
def _setup_templates(self):
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
_template_dir = f'{tmpdir}/templates'
|
||||
os.mkdir(_template_dir)
|
||||
with open(f'{_template_dir}/my-service.conf.j2', 'w') as f:
|
||||
f.write(TEMPLATE_CONTENTS)
|
||||
with open(f'{_template_dir}/wsgi-my-service.conf.j2', 'w') as f:
|
||||
f.write(TEMPLATE_CONTENTS)
|
||||
return _template_dir
|
||||
|
||||
def _log_event(self, event):
|
||||
self.seen_events.append(type(event).__name__)
|
||||
|
||||
def _on_service_pebble_ready(self, event):
|
||||
super()._on_service_pebble_ready(event)
|
||||
self._log_event(event)
|
||||
|
||||
def _on_config_changed(self, event):
|
||||
self._log_event(event)
|
||||
|
||||
@property
|
||||
def default_public_ingress_port(self):
|
||||
return 789
|
||||
|
||||
@property
|
||||
def template_dir(self):
|
||||
return self._template_dir
|
||||
|
||||
|
||||
class TestOSBaseOperatorAPICharm(CharmTestCase):
|
||||
class TestOSBaseOperatorAPICharm(test_utils.CharmTestCase):
|
||||
|
||||
PATCHES = [
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
container_calls = {
|
||||
self.container_calls = {
|
||||
'push': {},
|
||||
'pull': [],
|
||||
'remove_path': []}
|
||||
|
||||
super().setUp(sunbeam_charm, self.PATCHES)
|
||||
|
||||
class _OSTestingPebbleClient(_TestingPebbleClient):
|
||||
|
||||
def push(
|
||||
self, path, source, *,
|
||||
encoding='utf-8', make_dirs=False, permissions=None,
|
||||
user_id=None, user=None, group_id=None, group=None):
|
||||
container_calls['push'][path] = {
|
||||
'source': source,
|
||||
'permissions': permissions,
|
||||
'user': user,
|
||||
'group': group}
|
||||
|
||||
def pull(self, path, *, encoding='utf-8'):
|
||||
container_calls['pull'].append(path)
|
||||
reader = io.StringIO("0")
|
||||
return reader
|
||||
|
||||
def remove_path(self, path, *, recursive=False):
|
||||
container_calls['remove_path'].append(path)
|
||||
|
||||
class _OSTestingModelBackend(_TestingModelBackend):
|
||||
|
||||
def get_pebble(self, socket_path: str):
|
||||
client = self._pebble_clients.get(socket_path, None)
|
||||
if client is None:
|
||||
client = _OSTestingPebbleClient(self)
|
||||
self._pebble_clients[socket_path] = client
|
||||
return client
|
||||
|
||||
self.container_calls = container_calls
|
||||
# self.sunbeam_cprocess.ContainerProcessError = Exception
|
||||
self.harness = Harness(
|
||||
MyAPICharm,
|
||||
meta=API_CHARM_METADATA
|
||||
)
|
||||
self.harness._backend = _OSTestingModelBackend(
|
||||
self.harness._unit_name, self.harness._meta)
|
||||
self.harness._model = model.Model(
|
||||
self.harness._meta,
|
||||
self.harness._backend)
|
||||
self.harness._framework = framework.Framework(
|
||||
":memory:",
|
||||
self.harness._charm_dir,
|
||||
self.harness._meta,
|
||||
self.harness._model)
|
||||
# END Workaround
|
||||
self.harness = test_utils.get_harness(
|
||||
test_charms.MyAPICharm,
|
||||
test_charms.API_CHARM_METADATA,
|
||||
self.container_calls)
|
||||
|
||||
self.addCleanup(self.harness.cleanup)
|
||||
self.harness.update_config(CHARM_CONFIG)
|
||||
self.harness.update_config(test_charms.CHARM_CONFIG)
|
||||
self.harness.begin()
|
||||
|
||||
def add_base_amqp_relation(self):
|
||||
rel_id = self.harness.add_relation('amqp', 'rabbitmq')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'rabbitmq/0')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'rabbitmq/0')
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'rabbitmq/0',
|
||||
{'ingress-address': '10.0.0.13'})
|
||||
return rel_id
|
||||
|
||||
def add_amqp_relation_credentials(self, rel_id):
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'rabbitmq',
|
||||
{
|
||||
'hostname': 'rabbithost1.local',
|
||||
'password': 'rabbit.pass'})
|
||||
|
||||
def add_base_identity_service_relation(self):
|
||||
rel_id = self.harness.add_relation('identity-service', 'keystone')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'keystone/0')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'keystone/0')
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'keystone/0',
|
||||
{'ingress-address': '10.0.0.33'})
|
||||
return rel_id
|
||||
|
||||
def add_identity_service_relation_response(self, rel_id):
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'keystone',
|
||||
{
|
||||
'admin-domain-id': 'admindomid1',
|
||||
'admin-project-id': 'adminprojid1',
|
||||
'admin-user-id': 'adminuserid1',
|
||||
'api-version': '3',
|
||||
'auth-host': 'keystone.local',
|
||||
'auth-port': '12345',
|
||||
'auth-protocol': 'http',
|
||||
'internal-host': 'keystone.internal',
|
||||
'internal-port': '5000',
|
||||
'internal-protocol': 'http',
|
||||
'service-domain': 'servicedom',
|
||||
'service-domain_id': 'svcdomid1',
|
||||
'service-host': 'keystone.service',
|
||||
'service-password': 'svcpass1',
|
||||
'service-port': '5000',
|
||||
'service-protocol': 'http',
|
||||
'service-project': 'svcproj1',
|
||||
'service-project-id': 'svcprojid1',
|
||||
'service-username': 'svcuser1'})
|
||||
|
||||
def add_base_db_relation(self):
|
||||
rel_id = self.harness.add_relation('my-service-db', 'mysql')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'mysql/0')
|
||||
self.harness.add_relation_unit(
|
||||
rel_id,
|
||||
'mysql/0')
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'mysql/0',
|
||||
{'ingress-address': '10.0.0.3'})
|
||||
return rel_id
|
||||
|
||||
def add_db_relation_credentials(self, rel_id):
|
||||
self.harness.update_relation_data(
|
||||
rel_id,
|
||||
'mysql',
|
||||
{
|
||||
'databases': json.dumps(['db1']),
|
||||
'data': json.dumps({
|
||||
'credentials': {
|
||||
'username': 'foo',
|
||||
'password': 'hardpassword',
|
||||
'address': '10.0.0.10'}})})
|
||||
|
||||
def set_pebble_ready(self):
|
||||
self.harness.container_pebble_ready('my-service')
|
||||
|
||||
def test_write_config(self):
|
||||
self.harness.set_leader()
|
||||
self.set_pebble_ready()
|
||||
db_rel_id = self.add_base_db_relation()
|
||||
self.add_db_relation_credentials(db_rel_id)
|
||||
amqp_rel_id = self.add_base_amqp_relation()
|
||||
self.add_amqp_relation_credentials(amqp_rel_id)
|
||||
id_rel_id = self.add_base_identity_service_relation()
|
||||
self.add_identity_service_relation_response(id_rel_id)
|
||||
test_utils.add_api_relations(self.harness)
|
||||
expect_entries = [
|
||||
'/bin/wsgi_admin',
|
||||
'hardpassword',
|
||||
@ -465,10 +133,10 @@ class TestOSBaseOperatorAPICharm(CharmTestCase):
|
||||
def test__on_database_changed(self, _renderer):
|
||||
self.harness.set_leader()
|
||||
self.set_pebble_ready()
|
||||
rel_id = self.add_base_db_relation()
|
||||
self.add_db_relation_credentials(rel_id)
|
||||
db_rel_id = test_utils.add_base_db_relation(self.harness)
|
||||
test_utils.add_db_relation_credentials(self.harness, db_rel_id)
|
||||
rel_data = self.harness.get_relation_data(
|
||||
rel_id,
|
||||
db_rel_id,
|
||||
'my-service')
|
||||
requested_db = json.loads(rel_data['databases'])[0]
|
||||
self.assertRegex(requested_db, r'^db_.*my_service$')
|
||||
@ -476,8 +144,8 @@ class TestOSBaseOperatorAPICharm(CharmTestCase):
|
||||
def test_contexts(self):
|
||||
self.harness.set_leader()
|
||||
self.set_pebble_ready()
|
||||
rel_id = self.add_base_db_relation()
|
||||
self.add_db_relation_credentials(rel_id)
|
||||
db_rel_id = test_utils.add_base_db_relation(self.harness)
|
||||
test_utils.add_db_relation_credentials(self.harness, db_rel_id)
|
||||
contexts = self.harness.charm.contexts()
|
||||
self.assertEqual(
|
||||
contexts.wsgi_config.wsgi_admin_script,
|
||||
|
Loading…
Reference in New Issue
Block a user