Add Keystone charm
[osm/devops.git] / installers / charm / osm-keystone / tests / unit / test_charm.py
1 # Copyright 2021 Canonical Ltd.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14 #
15 # For those usages not covered by the Apache License, Version 2.0 please
16 # contact: legal@canonical.com
17 #
18
19 import pytest
20 from ops import pebble
21 from ops.model import ActiveStatus, BlockedStatus
22 from ops.testing import Harness
23 from pytest_mock import MockerFixture
24
25 from charm import FERNET_KEY_REPOSITORY, KEYSTONE_FOLDER, KeystoneCharm
26
27
28 @pytest.fixture
29 def harness_no_relations(mocker: MockerFixture):
30 mocker.patch("charm.cluster")
31 mocker.patch("charm.KubernetesServicePatch")
32 keystone_harness = Harness(KeystoneCharm)
33 keystone_harness.begin()
34 container = keystone_harness.charm.unit.get_container("keystone")
35 keystone_harness.set_can_connect(container, True)
36 container.make_dir(KEYSTONE_FOLDER, make_parents=True)
37 container.make_dir(FERNET_KEY_REPOSITORY, make_parents=True)
38 container.push(f"{FERNET_KEY_REPOSITORY}0", "token")
39 container.make_dir("/app", make_parents=True)
40 container.push("/app/start.sh", "")
41 container.exec = mocker.Mock()
42 yield keystone_harness
43 keystone_harness.cleanup()
44
45
46 @pytest.fixture
47 def harness(harness_no_relations: Harness):
48 mysql_rel_id = harness_no_relations.add_relation("db", "mysql")
49 harness_no_relations.add_relation_unit(mysql_rel_id, "mysql/0")
50 harness_no_relations.update_relation_data(
51 mysql_rel_id,
52 "mysql/0",
53 {
54 "host": "host",
55 "port": "3306",
56 "user": "user",
57 "root_password": "root_pass",
58 "password": "password",
59 "database": "db",
60 },
61 )
62 return harness_no_relations
63
64
65 def test_mysql_missing_relation(mocker: MockerFixture, harness_no_relations: Harness):
66 spy_safe_restart = mocker.spy(harness_no_relations.charm, "_safe_restart")
67 harness_no_relations.charm.on.keystone_pebble_ready.emit("keystone")
68 assert harness_no_relations.charm.unit.status == BlockedStatus("mysql relation is missing")
69 assert spy_safe_restart.call_count == 1
70 harness_no_relations.charm.on.config_changed.emit()
71 assert harness_no_relations.charm.unit.status == BlockedStatus("mysql relation is missing")
72 assert spy_safe_restart.call_count == 2
73
74
75 def test_mysql_relation_ready(mocker: MockerFixture, harness: Harness):
76 spy = mocker.spy(harness.charm, "_safe_restart")
77 harness.charm.on.config_changed.emit()
78 assert harness.charm.unit.status == ActiveStatus()
79 assert spy.call_count == 1
80
81
82 def test_db_sync_action(mocker: MockerFixture, harness: Harness):
83 event_mock = mocker.Mock()
84 harness.charm._on_db_sync_action(event_mock)
85 event_mock.set_results.assert_called_once_with(
86 {"output": "db-sync was successfully executed."}
87 )
88 event_mock.fail.assert_not_called()
89 harness.charm.container.exec().wait.side_effect = pebble.ExecError(
90 ["keystone-manage", "db_sync"], 1, "", "Error"
91 )
92 harness.charm._on_db_sync_action(event_mock)
93 event_mock.fail.assert_called_once_with("db-sync action failed with code 1 and stderr Error.")
94
95
96 def test_provide_keystone_relation(mocker: MockerFixture, harness: Harness):
97 # Non-leader
98 mon_rel_id = harness.add_relation("keystone", "mon")
99 harness.add_relation_unit(mon_rel_id, "mon/0")
100 data = harness.get_relation_data(mon_rel_id, harness.charm.app)
101 assert data == {}
102 # Leader
103 harness.set_leader(True)
104 nbi_rel_id = harness.add_relation("keystone", "nbi")
105 harness.add_relation_unit(nbi_rel_id, "nbi/0")
106 data = harness.get_relation_data(nbi_rel_id, harness.charm.app)
107 assert data == {
108 "host": "http://osm-keystone:5000/v3",
109 "port": "5000",
110 "user_domain_name": "default",
111 "project_domain_name": "default",
112 "username": "nbi",
113 "password": "nbi",
114 "service": "service",
115 "keystone_db_password": "admin",
116 "region_id": "RegionOne",
117 "admin_username": "admin",
118 "admin_password": "admin",
119 "admin_project_name": "admin",
120 }
121
122
123 def test_update_status_rotation(mocker: MockerFixture, harness: Harness):
124 spy_fernet_rotate = mocker.spy(harness.charm, "_fernet_rotate")
125 harness.set_leader(True)
126 harness._update_config({"token-expiration": -1})
127 harness.charm.on.update_status.emit()
128 assert spy_fernet_rotate.call_count == 1
129
130
131 def test_update_status_no_rotation(mocker: MockerFixture, harness: Harness):
132 spy_fernet_rotate = mocker.spy(harness.charm, "_fernet_rotate")
133 harness.set_leader(True)
134 harness._update_config({"token-expiration": 3600})
135 harness.charm.on.update_status.emit()
136 assert spy_fernet_rotate.call_count == 0