Merge ~ballot/charm-k8s-mm-pd-bot/+git/charm-k8s-mm-pd-bot:quotes into charm-k8s-mm-pd-bot:master
- Git
- lp:~ballot/charm-k8s-mm-pd-bot/+git/charm-k8s-mm-pd-bot
- quotes
- Merge into master
Proposed by
Benjamin Allot
Status: | Merged |
---|---|
Approved by: | Benjamin Allot |
Approved revision: | 8d9e09b73c39cb2d02f2975762942c830e966e9f |
Merged at revision: | 8671d0b6c001cc0e0ae09865386645511af1c755 |
Proposed branch: | ~ballot/charm-k8s-mm-pd-bot/+git/charm-k8s-mm-pd-bot:quotes |
Merge into: | charm-k8s-mm-pd-bot:master |
Diff against target: |
727 lines (+210/-211) 4 files modified
pyproject.toml (+0/-1) src/charm.py (+41/-41) tests/unit/scenario.py (+143/-143) tests/unit/test_charm.py (+26/-26) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurent Sesquès | Approve | ||
Canonical IS Reviewers | Pending | ||
Review via email:
|
Commit message
Normalize quotes with black
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Change successfully merged at revision 8671d0b6c001cc0
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/pyproject.toml b/pyproject.toml | |||
2 | index d2f23b9..55ec8d7 100644 | |||
3 | --- a/pyproject.toml | |||
4 | +++ b/pyproject.toml | |||
5 | @@ -1,3 +1,2 @@ | |||
6 | 1 | [tool.black] | 1 | [tool.black] |
7 | 2 | skip-string-normalization = true | ||
8 | 3 | line-length = 120 | 2 | line-length = 120 |
9 | diff --git a/src/charm.py b/src/charm.py | |||
10 | index b17ced0..7b2807f 100755 | |||
11 | --- a/src/charm.py | |||
12 | +++ b/src/charm.py | |||
13 | @@ -18,18 +18,18 @@ from ops.model import ( | |||
14 | 18 | 18 | ||
15 | 19 | logger = logging.getLogger() | 19 | logger = logging.getLogger() |
16 | 20 | 20 | ||
18 | 21 | REQUIRED_JUJU_SETTINGS = ['image_path', 'mm_pd_bot_cfg'] | 21 | REQUIRED_JUJU_SETTINGS = ["image_path", "mm_pd_bot_cfg"] |
19 | 22 | REQUIRED_CFG_SETTINGS = { | 22 | REQUIRED_CFG_SETTINGS = { |
24 | 23 | 'PagerDuty': ['account', 'api-token', 'private-channel', 'public-channel'], | 23 | "PagerDuty": ["account", "api-token", "private-channel", "public-channel"], |
25 | 24 | 'Prometheus': ['max_cache_size'], | 24 | "Prometheus": ["max_cache_size"], |
26 | 25 | 'httpd': ['hostname', 'listen-ip', 'listen-port', 'magic-uuid'], | 25 | "httpd": ["hostname", "listen-ip", "listen-port", "magic-uuid"], |
27 | 26 | 'MattermostBot': ['bot_url', 'bot_team'], | 26 | "MattermostBot": ["bot_url", "bot_team"], |
28 | 27 | # Those sections can be empty | 27 | # Those sections can be empty |
32 | 28 | 'nickname to email': [], | 28 | "nickname to email": [], |
33 | 29 | 'Mattermost Aliases': [], | 29 | "Mattermost Aliases": [], |
34 | 30 | 'PagerDuty service to Mattermost Channel': [], | 30 | "PagerDuty service to Mattermost Channel": [], |
35 | 31 | } | 31 | } |
37 | 32 | BOT_CFG_SECTION = 'MattermostBot' | 32 | BOT_CFG_SECTION = "MattermostBot" |
38 | 33 | 33 | ||
39 | 34 | 34 | ||
40 | 35 | class MmPdBotK8sCharmConfigError(Exception): | 35 | class MmPdBotK8sCharmConfigError(Exception): |
41 | @@ -51,9 +51,9 @@ class MmPdBotK8sCharm(CharmBase): | |||
42 | 51 | :raises MmPdBotK8sCharmConfigError: Raise if you don't have a bot_token or the combination of bot_login and | 51 | :raises MmPdBotK8sCharmConfigError: Raise if you don't have a bot_token or the combination of bot_login and |
43 | 52 | bot_password. | 52 | bot_password. |
44 | 53 | """ | 53 | """ |
48 | 54 | bot_token = self.bot_config.get(BOT_CFG_SECTION, 'bot_token', fallback=None) | 54 | bot_token = self.bot_config.get(BOT_CFG_SECTION, "bot_token", fallback=None) |
49 | 55 | bot_login = self.bot_config.get(BOT_CFG_SECTION, 'bot_login', fallback=None) | 55 | bot_login = self.bot_config.get(BOT_CFG_SECTION, "bot_login", fallback=None) |
50 | 56 | bot_password = self.bot_config.get(BOT_CFG_SECTION, 'bot_password', fallback=None) | 56 | bot_password = self.bot_config.get(BOT_CFG_SECTION, "bot_password", fallback=None) |
51 | 57 | 57 | ||
52 | 58 | if not bot_token and (not bot_login or not bot_password): | 58 | if not bot_token and (not bot_login or not bot_password): |
53 | 59 | err_msg = "bot_token or bot_login/bot_password in {0} section required".format(BOT_CFG_SECTION) | 59 | err_msg = "bot_token or bot_login/bot_password in {0} section required".format(BOT_CFG_SECTION) |
54 | @@ -129,7 +129,7 @@ class MmPdBotK8sCharm(CharmBase): | |||
55 | 129 | 129 | ||
56 | 130 | def _validate_mm_pd_bot_configuration(self) -> None: | 130 | def _validate_mm_pd_bot_configuration(self) -> None: |
57 | 131 | """Check the configuration part related to mm_pd_bot configuration.""" | 131 | """Check the configuration part related to mm_pd_bot configuration.""" |
59 | 132 | self.bot_config = self._load_mm_pd_bot_configuration(self.model.config['mm_pd_bot_cfg']) | 132 | self.bot_config = self._load_mm_pd_bot_configuration(self.model.config["mm_pd_bot_cfg"]) |
60 | 133 | self._validate_mm_pd_bot_configuration_content() | 133 | self._validate_mm_pd_bot_configuration_content() |
61 | 134 | self._validate_bot_creds() | 134 | self._validate_bot_creds() |
62 | 135 | 135 | ||
63 | @@ -148,7 +148,7 @@ class MmPdBotK8sCharm(CharmBase): | |||
64 | 148 | """ | 148 | """ |
65 | 149 | config = self.model.config | 149 | config = self.model.config |
66 | 150 | pod_config = { | 150 | pod_config = { |
68 | 151 | 'MM_PD_BOT_CFG': config['mm_pd_bot_cfg'], | 151 | "MM_PD_BOT_CFG": config["mm_pd_bot_cfg"], |
69 | 152 | } | 152 | } |
70 | 153 | 153 | ||
71 | 154 | return pod_config | 154 | return pod_config |
72 | @@ -159,10 +159,10 @@ class MmPdBotK8sCharm(CharmBase): | |||
73 | 159 | :param pod_spec: pod spec v3 as defined by juju. | 159 | :param pod_spec: pod spec v3 as defined by juju. |
74 | 160 | """ | 160 | """ |
75 | 161 | 161 | ||
80 | 162 | hostname = self.bot_config.get('httpd', 'hostname') | 162 | hostname = self.bot_config.get("httpd", "hostname") |
81 | 163 | container_port = self.bot_config.getint('httpd', 'listen-port') | 163 | container_port = self.bot_config.getint("httpd", "listen-port") |
82 | 164 | magic_uuid = self.bot_config.get('httpd', 'magic-uuid') | 164 | magic_uuid = self.bot_config.get("httpd", "magic-uuid") |
83 | 165 | tls_secret_name = self.model.config.get('tls_secret_name', None) | 165 | tls_secret_name = self.model.config.get("tls_secret_name", None) |
84 | 166 | 166 | ||
85 | 167 | if tls_secret_name: | 167 | if tls_secret_name: |
86 | 168 | scheme = "https" | 168 | scheme = "https" |
87 | @@ -192,52 +192,52 @@ class MmPdBotK8sCharm(CharmBase): | |||
88 | 192 | }, | 192 | }, |
89 | 193 | } | 193 | } |
90 | 194 | if tls_secret_name: | 194 | if tls_secret_name: |
93 | 195 | ingress['spec']['tls'] = [ | 195 | ingress["spec"]["tls"] = [ |
94 | 196 | {'hosts': [bot_listening_url_parsed.hostname], 'secretName': tls_secret_name}, | 196 | {"hosts": [bot_listening_url_parsed.hostname], "secretName": tls_secret_name}, |
95 | 197 | ] | 197 | ] |
96 | 198 | else: | 198 | else: |
98 | 199 | annotations['nginx.ingress.kubernetes.io/ssl-redirect'] = 'false' | 199 | annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false" |
99 | 200 | 200 | ||
101 | 201 | ingress_whitelist_source_range = self.model.config.get('ingress_whitelist_source_range', None) | 201 | ingress_whitelist_source_range = self.model.config.get("ingress_whitelist_source_range", None) |
102 | 202 | if ingress_whitelist_source_range: | 202 | if ingress_whitelist_source_range: |
104 | 203 | annotations['nginx.ingress.kubernetes.io/whitelist-source-range'] = ingress_whitelist_source_range | 203 | annotations["nginx.ingress.kubernetes.io/whitelist-source-range"] = ingress_whitelist_source_range |
105 | 204 | 204 | ||
106 | 205 | if annotations: | 205 | if annotations: |
108 | 206 | ingress['annotations'] = annotations | 206 | ingress["annotations"] = annotations |
109 | 207 | 207 | ||
110 | 208 | # Due to https://github.com/canonical/operator/issues/293 we | 208 | # Due to https://github.com/canonical/operator/issues/293 we |
111 | 209 | # can't use pod.set_spec's k8s_resources argument. | 209 | # can't use pod.set_spec's k8s_resources argument. |
115 | 210 | resources = pod_spec.get('kubernetesResources', {}) | 210 | resources = pod_spec.get("kubernetesResources", {}) |
116 | 211 | resources['ingressResources'] = [ingress] | 211 | resources["ingressResources"] = [ingress] |
117 | 212 | pod_spec['kubernetesResources'] = resources | 212 | pod_spec["kubernetesResources"] = resources |
118 | 213 | 213 | ||
119 | 214 | def _make_pod_spec(self) -> None: | 214 | def _make_pod_spec(self) -> None: |
120 | 215 | """Create a pod spec with some core configuration.""" | 215 | """Create a pod spec with some core configuration.""" |
121 | 216 | 216 | ||
122 | 217 | config = self.model.config | 217 | config = self.model.config |
124 | 218 | container_port = self.bot_config.getint('httpd', 'listen-port') | 218 | container_port = self.bot_config.getint("httpd", "listen-port") |
125 | 219 | # TODO: The bot replies 501 on HTTP GET so until we have something to probe readiness, magic-uuid is not needed | 219 | # TODO: The bot replies 501 on HTTP GET so until we have something to probe readiness, magic-uuid is not needed |
126 | 220 | # here | 220 | # here |
127 | 221 | # magic_uuid = self.bot_config.get('httpd', 'magic-uuid') | 221 | # magic_uuid = self.bot_config.get('httpd', 'magic-uuid') |
128 | 222 | image_details = { | 222 | image_details = { |
130 | 223 | 'imagePath': config['image_path'], | 223 | "imagePath": config["image_path"], |
131 | 224 | } | 224 | } |
134 | 225 | if config.get('image_username', None): | 225 | if config.get("image_username", None): |
135 | 226 | image_details.update({'username': config['image_username'], 'password': config['image_password']}) | 226 | image_details.update({"username": config["image_username"], "password": config["image_password"]}) |
136 | 227 | pod_config = self._make_pod_config() | 227 | pod_config = self._make_pod_config() |
137 | 228 | 228 | ||
138 | 229 | return { | 229 | return { |
141 | 230 | 'version': 3, # otherwise resources are ignored | 230 | "version": 3, # otherwise resources are ignored |
142 | 231 | 'containers': [ | 231 | "containers": [ |
143 | 232 | { | 232 | { |
146 | 233 | 'name': self.app.name, | 233 | "name": self.app.name, |
147 | 234 | 'imageDetails': image_details, | 234 | "imageDetails": image_details, |
148 | 235 | # TODO: debatable. The idea is that if you want to force an update with the same image name, you | 235 | # TODO: debatable. The idea is that if you want to force an update with the same image name, you |
149 | 236 | # don't need to empty kubelet cache on each node to have the right version. | 236 | # don't need to empty kubelet cache on each node to have the right version. |
150 | 237 | # This implies a performance drop upon start. | 237 | # This implies a performance drop upon start. |
154 | 238 | 'imagePullPolicy': 'Always', | 238 | "imagePullPolicy": "Always", |
155 | 239 | 'ports': [{'containerPort': container_port, 'protocol': 'TCP'}], | 239 | "ports": [{"containerPort": container_port, "protocol": "TCP"}], |
156 | 240 | 'envConfig': pod_config, | 240 | "envConfig": pod_config, |
157 | 241 | # TODO: Add readiness probe in the bot. | 241 | # TODO: Add readiness probe in the bot. |
158 | 242 | # 'kubernetes': { | 242 | # 'kubernetes': { |
159 | 243 | # 'readinessProbe': {'httpGet': {'path': '/{0}/'.format(magic_uuid), 'port': container_port}}, | 243 | # 'readinessProbe': {'httpGet': {'path': '/{0}/'.format(magic_uuid), 'port': container_port}}, |
160 | @@ -261,13 +261,13 @@ class MmPdBotK8sCharm(CharmBase): | |||
161 | 261 | self.unit.status = BlockedStatus(str(exc)) | 261 | self.unit.status = BlockedStatus(str(exc)) |
162 | 262 | return | 262 | return |
163 | 263 | 263 | ||
165 | 264 | logger.info('Assembling pod spec') | 264 | logger.info("Assembling pod spec") |
166 | 265 | pod_spec = self._make_pod_spec() | 265 | pod_spec = self._make_pod_spec() |
167 | 266 | self._update_pod_spec_for_k8s_ingress(pod_spec) | 266 | self._update_pod_spec_for_k8s_ingress(pod_spec) |
169 | 267 | logger.info('Setting pod spec') | 267 | logger.info("Setting pod spec") |
170 | 268 | self.model.pod.set_spec(pod_spec) | 268 | self.model.pod.set_spec(pod_spec) |
171 | 269 | self.unit.status = ActiveStatus() | 269 | self.unit.status = ActiveStatus() |
172 | 270 | 270 | ||
173 | 271 | 271 | ||
175 | 272 | if __name__ == '__main__': # pragma: no cover | 272 | if __name__ == "__main__": # pragma: no cover |
176 | 273 | main(MmPdBotK8sCharm, use_juju_for_storage=True) | 273 | main(MmPdBotK8sCharm, use_juju_for_storage=True) |
177 | diff --git a/tests/unit/scenario.py b/tests/unit/scenario.py | |||
178 | index 9c62641..4aa55b5 100644 | |||
179 | --- a/tests/unit/scenario.py | |||
180 | +++ b/tests/unit/scenario.py | |||
181 | @@ -12,16 +12,16 @@ import yaml | |||
182 | 12 | logger = logging.getLogger(__name__) | 12 | logger = logging.getLogger(__name__) |
183 | 13 | 13 | ||
184 | 14 | BOT_CFG_FILES = { | 14 | BOT_CFG_FILES = { |
191 | 15 | 'both_authentication_method': 'both_authentication_method.cfg', | 15 | "both_authentication_method": "both_authentication_method.cfg", |
192 | 16 | 'good_configuration': 'good_bot.cfg', | 16 | "good_configuration": "good_bot.cfg", |
193 | 17 | 'missing_options': 'missing_options.cfg', | 17 | "missing_options": "missing_options.cfg", |
194 | 18 | 'missing_sections': 'missing_sections.cfg', | 18 | "missing_sections": "missing_sections.cfg", |
195 | 19 | 'no_valid_authentication': 'no_valid_authentication.cfg', | 19 | "no_valid_authentication": "no_valid_authentication.cfg", |
196 | 20 | 'ssl_configuration': 'ssl_bot.cfg', | 20 | "ssl_configuration": "ssl_bot.cfg", |
197 | 21 | } | 21 | } |
198 | 22 | 22 | ||
199 | 23 | 23 | ||
201 | 24 | def get_cfg_content(configuration='good_configuration') -> str: | 24 | def get_cfg_content(configuration="good_configuration") -> str: |
202 | 25 | """Get the content of the file associated with configuration. | 25 | """Get the content of the file associated with configuration. |
203 | 26 | 26 | ||
204 | 27 | :param str configuration: Key of the BOT_CFG_FILES dictionary to get the content of the associated configuration | 27 | :param str configuration: Key of the BOT_CFG_FILES dictionary to get the content of the associated configuration |
205 | @@ -32,7 +32,7 @@ def get_cfg_content(configuration='good_configuration') -> str: | |||
206 | 32 | files_dir = "files" | 32 | files_dir = "files" |
207 | 33 | try: | 33 | try: |
208 | 34 | path = Path(dir_path, files_dir, BOT_CFG_FILES[configuration]) | 34 | path = Path(dir_path, files_dir, BOT_CFG_FILES[configuration]) |
210 | 35 | with open(path, 'r') as cfg: | 35 | with open(path, "r") as cfg: |
211 | 36 | return cfg.read() | 36 | return cfg.read() |
212 | 37 | except KeyError: | 37 | except KeyError: |
213 | 38 | logger.error("No configuration files associated with '%s'", configuration) | 38 | logger.error("No configuration files associated with '%s'", configuration) |
214 | @@ -43,12 +43,12 @@ def get_juju_settings_default_value() -> list: | |||
215 | 43 | """Return the list of juju settings as defined in config.yaml.""" | 43 | """Return the list of juju settings as defined in config.yaml.""" |
216 | 44 | 44 | ||
217 | 45 | dir_path = os.path.dirname(os.path.realpath(__file__)) | 45 | dir_path = os.path.dirname(os.path.realpath(__file__)) |
220 | 46 | config_yaml = Path(dir_path, '..', '..', 'config.yaml') | 46 | config_yaml = Path(dir_path, "..", "..", "config.yaml") |
221 | 47 | with open(config_yaml, 'r') as config: | 47 | with open(config_yaml, "r") as config: |
222 | 48 | loaded_config = yaml.safe_load(config.read()) | 48 | loaded_config = yaml.safe_load(config.read()) |
223 | 49 | 49 | ||
224 | 50 | # Load the dict with the default values | 50 | # Load the dict with the default values |
226 | 51 | default_values = {config: value['default'] for (config, value) in loaded_config['options'].items()} | 51 | default_values = {config: value["default"] for (config, value) in loaded_config["options"].items()} |
227 | 52 | 52 | ||
228 | 53 | return default_values | 53 | return default_values |
229 | 54 | 54 | ||
230 | @@ -57,52 +57,52 @@ def get_juju_settings_default_value() -> list: | |||
231 | 57 | JUJU_SETTINGS_DEFAULT = get_juju_settings_default_value() | 57 | JUJU_SETTINGS_DEFAULT = get_juju_settings_default_value() |
232 | 58 | 58 | ||
233 | 59 | TEST_JUJU_SETTINGS = { | 59 | TEST_JUJU_SETTINGS = { |
238 | 60 | 'empty_image_path': { | 60 | "empty_image_path": { |
239 | 61 | 'config': {'mm_pd_bot_cfg': 'dummy'}, | 61 | "config": {"mm_pd_bot_cfg": "dummy"}, |
240 | 62 | 'logger': ["ERROR:root:Required setting empty: image_path"], | 62 | "logger": ["ERROR:root:Required setting empty: image_path"], |
241 | 63 | 'expected': 'Required setting(s) empty: image_path', | 63 | "expected": "Required setting(s) empty: image_path", |
242 | 64 | }, | 64 | }, |
247 | 65 | 'empty_mm_pd_bot_cfg': { | 65 | "empty_mm_pd_bot_cfg": { |
248 | 66 | 'config': {'image_path': 'mm_pd_bot:devel'}, | 66 | "config": {"image_path": "mm_pd_bot:devel"}, |
249 | 67 | 'logger': ["ERROR:root:Required setting empty: mm_pd_bot_cfg"], | 67 | "logger": ["ERROR:root:Required setting empty: mm_pd_bot_cfg"], |
250 | 68 | 'expected': 'Required setting(s) empty: mm_pd_bot_cfg', | 68 | "expected": "Required setting(s) empty: mm_pd_bot_cfg", |
251 | 69 | }, | 69 | }, |
256 | 70 | 'empty_all_settings': { | 70 | "empty_all_settings": { |
257 | 71 | 'config': {}, | 71 | "config": {}, |
258 | 72 | 'logger': ["ERROR:root:Required setting empty: image_path", "ERROR:root:Required setting empty: mm_pd_bot_cfg"], | 72 | "logger": ["ERROR:root:Required setting empty: image_path", "ERROR:root:Required setting empty: mm_pd_bot_cfg"], |
259 | 73 | 'expected': 'Required setting(s) empty: image_path, mm_pd_bot_cfg', | 73 | "expected": "Required setting(s) empty: image_path, mm_pd_bot_cfg", |
260 | 74 | }, | 74 | }, |
261 | 75 | } | 75 | } |
262 | 76 | 76 | ||
263 | 77 | 77 | ||
264 | 78 | VALIDATE_MM_PD_BOT_CFG = { | 78 | VALIDATE_MM_PD_BOT_CFG = { |
269 | 79 | 'good_configuration': { | 79 | "good_configuration": { |
270 | 80 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': get_cfg_content("good_configuration")}, | 80 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": get_cfg_content("good_configuration")}, |
271 | 81 | 'expected': True, | 81 | "expected": True, |
272 | 82 | 'logger': [], | 82 | "logger": [], |
273 | 83 | }, | 83 | }, |
278 | 84 | 'bad_formatted_configuration': { | 84 | "bad_formatted_configuration": { |
279 | 85 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': "[PagerDuty"}, | 85 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": "[PagerDuty"}, |
280 | 86 | 'expected': "Error while parsing mm_pd_bot_cfg setting", | 86 | "expected": "Error while parsing mm_pd_bot_cfg setting", |
281 | 87 | 'logger': ["ERROR:root:Error while parsing mm_pd_bot_cfg setting"], | 87 | "logger": ["ERROR:root:Error while parsing mm_pd_bot_cfg setting"], |
282 | 88 | }, | 88 | }, |
286 | 89 | 'missing_sections': { | 89 | "missing_sections": { |
287 | 90 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': get_cfg_content('missing_sections')}, | 90 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": get_cfg_content("missing_sections")}, |
288 | 91 | 'expected': "Required section(s) missing in bot configuration file: " | 91 | "expected": "Required section(s) missing in bot configuration file: " |
289 | 92 | "MattermostBot, Prometheus, httpd, nickname to email", | 92 | "MattermostBot, Prometheus, httpd, nickname to email", |
291 | 93 | 'logger': [ | 93 | "logger": [ |
292 | 94 | "ERROR:root:required section missing in bot configuration file: httpd", | 94 | "ERROR:root:required section missing in bot configuration file: httpd", |
293 | 95 | "ERROR:root:required section missing in bot configuration file: MattermostBot", | 95 | "ERROR:root:required section missing in bot configuration file: MattermostBot", |
294 | 96 | "ERROR:root:required section missing in bot configuration file: Prometheus", | 96 | "ERROR:root:required section missing in bot configuration file: Prometheus", |
295 | 97 | "ERROR:root:required section missing in bot configuration file: nickname to email", | 97 | "ERROR:root:required section missing in bot configuration file: nickname to email", |
296 | 98 | ], | 98 | ], |
297 | 99 | }, | 99 | }, |
301 | 100 | 'missing_options': { | 100 | "missing_options": { |
302 | 101 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': get_cfg_content('missing_options')}, | 101 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": get_cfg_content("missing_options")}, |
303 | 102 | 'expected': "Required option(s) missing in section MattermostBot: bot_team, bot_url, " | 102 | "expected": "Required option(s) missing in section MattermostBot: bot_team, bot_url, " |
304 | 103 | "Required option(s) missing in section PagerDuty: api-token, " | 103 | "Required option(s) missing in section PagerDuty: api-token, " |
305 | 104 | "Required option(s) missing in section httpd: hostname, listen-ip, listen-port, magic-uuid", | 104 | "Required option(s) missing in section httpd: hostname, listen-ip, listen-port, magic-uuid", |
307 | 105 | 'logger': [ | 105 | "logger": [ |
308 | 106 | "ERROR:root:required option api-token missing in section PagerDuty", | 106 | "ERROR:root:required option api-token missing in section PagerDuty", |
309 | 107 | "ERROR:root:required option bot_team missing in section MattermostBot", | 107 | "ERROR:root:required option bot_team missing in section MattermostBot", |
310 | 108 | "ERROR:root:required option bot_url missing in section MattermostBot", | 108 | "ERROR:root:required option bot_url missing in section MattermostBot", |
311 | @@ -112,52 +112,52 @@ VALIDATE_MM_PD_BOT_CFG = { | |||
312 | 112 | "ERROR:root:required option magic-uuid missing in section httpd", | 112 | "ERROR:root:required option magic-uuid missing in section httpd", |
313 | 113 | ], | 113 | ], |
314 | 114 | }, | 114 | }, |
319 | 115 | 'no_valid_authentication': { | 115 | "no_valid_authentication": { |
320 | 116 | 'config': {'mm_pd_bot_cfg': get_cfg_content('no_valid_authentication')}, | 116 | "config": {"mm_pd_bot_cfg": get_cfg_content("no_valid_authentication")}, |
321 | 117 | 'expected': "bot_token or bot_login/bot_password in MattermostBot section required", | 117 | "expected": "bot_token or bot_login/bot_password in MattermostBot section required", |
322 | 118 | 'logger': ["ERROR:root:bot_token or bot_login/bot_password in MattermostBot section required"], | 118 | "logger": ["ERROR:root:bot_token or bot_login/bot_password in MattermostBot section required"], |
323 | 119 | }, | 119 | }, |
328 | 120 | 'both_authentication_method': { | 120 | "both_authentication_method": { |
329 | 121 | 'config': {'mm_pd_bot_cfg': get_cfg_content('both_authentication_method')}, | 121 | "config": {"mm_pd_bot_cfg": get_cfg_content("both_authentication_method")}, |
330 | 122 | 'expected': "bot_token and bot_login are both set. Pick one of them", | 122 | "expected": "bot_token and bot_login are both set. Pick one of them", |
331 | 123 | 'logger': ["ERROR:root:bot_token and bot_login are both set. Pick one of them"], | 123 | "logger": ["ERROR:root:bot_token and bot_login are both set. Pick one of them"], |
332 | 124 | }, | 124 | }, |
333 | 125 | } | 125 | } |
334 | 126 | 126 | ||
335 | 127 | VALIDATE_POD_SPEC = { | 127 | VALIDATE_POD_SPEC = { |
341 | 128 | 'basic': { | 128 | "basic": { |
342 | 129 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': get_cfg_content('good_configuration')}, | 129 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": get_cfg_content("good_configuration")}, |
343 | 130 | 'pod_spec': { | 130 | "pod_spec": { |
344 | 131 | 'version': 3, # otherwise resources are ignored | 131 | "version": 3, # otherwise resources are ignored |
345 | 132 | 'containers': [ | 132 | "containers": [ |
346 | 133 | { | 133 | { |
350 | 134 | 'name': 'mm-pd-bot', | 134 | "name": "mm-pd-bot", |
351 | 135 | 'imageDetails': { | 135 | "imageDetails": { |
352 | 136 | 'imagePath': 'mm_pd_bot:devel', | 136 | "imagePath": "mm_pd_bot:devel", |
353 | 137 | }, | 137 | }, |
357 | 138 | 'imagePullPolicy': 'Always', | 138 | "imagePullPolicy": "Always", |
358 | 139 | 'ports': [{'containerPort': 2160, 'protocol': 'TCP'}], | 139 | "ports": [{"containerPort": 2160, "protocol": "TCP"}], |
359 | 140 | 'envConfig': {'MM_PD_BOT_CFG': get_cfg_content('good_configuration')}, | 140 | "envConfig": {"MM_PD_BOT_CFG": get_cfg_content("good_configuration")}, |
360 | 141 | } | 141 | } |
361 | 142 | ], | 142 | ], |
362 | 143 | }, | 143 | }, |
363 | 144 | }, | 144 | }, |
370 | 145 | 'private_registry': { | 145 | "private_registry": { |
371 | 146 | 'config': { | 146 | "config": { |
372 | 147 | 'image_path': 'mm_pd_bot:devel', | 147 | "image_path": "mm_pd_bot:devel", |
373 | 148 | 'image_username': 'rockity', | 148 | "image_username": "rockity", |
374 | 149 | 'image_password': 'rock', | 149 | "image_password": "rock", |
375 | 150 | 'mm_pd_bot_cfg': get_cfg_content('good_configuration'), | 150 | "mm_pd_bot_cfg": get_cfg_content("good_configuration"), |
376 | 151 | }, | 151 | }, |
380 | 152 | 'pod_spec': { | 152 | "pod_spec": { |
381 | 153 | 'version': 3, # otherwise resources are ignored | 153 | "version": 3, # otherwise resources are ignored |
382 | 154 | 'containers': [ | 154 | "containers": [ |
383 | 155 | { | 155 | { |
389 | 156 | 'name': 'mm-pd-bot', | 156 | "name": "mm-pd-bot", |
390 | 157 | 'imageDetails': {'imagePath': 'mm_pd_bot:devel', 'username': 'rockity', 'password': 'rock'}, | 157 | "imageDetails": {"imagePath": "mm_pd_bot:devel", "username": "rockity", "password": "rock"}, |
391 | 158 | 'imagePullPolicy': 'Always', | 158 | "imagePullPolicy": "Always", |
392 | 159 | 'ports': [{'containerPort': 2160, 'protocol': 'TCP'}], | 159 | "ports": [{"containerPort": 2160, "protocol": "TCP"}], |
393 | 160 | 'envConfig': {'MM_PD_BOT_CFG': get_cfg_content('good_configuration')}, | 160 | "envConfig": {"MM_PD_BOT_CFG": get_cfg_content("good_configuration")}, |
394 | 161 | } | 161 | } |
395 | 162 | ], | 162 | ], |
396 | 163 | }, | 163 | }, |
397 | @@ -166,124 +166,124 @@ VALIDATE_POD_SPEC = { | |||
398 | 166 | 166 | ||
399 | 167 | 167 | ||
400 | 168 | VALIDATE_POD_SPEC_AND_INGRESS = { | 168 | VALIDATE_POD_SPEC_AND_INGRESS = { |
406 | 169 | 'basic': { | 169 | "basic": { |
407 | 170 | 'config': {'image_path': 'mm_pd_bot:devel', 'mm_pd_bot_cfg': get_cfg_content('good_configuration')}, | 170 | "config": {"image_path": "mm_pd_bot:devel", "mm_pd_bot_cfg": get_cfg_content("good_configuration")}, |
408 | 171 | 'pod_spec': { | 171 | "pod_spec": { |
409 | 172 | 'version': 3, # otherwise resources are ignored | 172 | "version": 3, # otherwise resources are ignored |
410 | 173 | 'containers': [ | 173 | "containers": [ |
411 | 174 | { | 174 | { |
417 | 175 | 'name': 'mm-pd-bot', | 175 | "name": "mm-pd-bot", |
418 | 176 | 'imageDetails': {'imagePath': 'mm_pd_bot:devel'}, | 176 | "imageDetails": {"imagePath": "mm_pd_bot:devel"}, |
419 | 177 | 'imagePullPolicy': 'Always', | 177 | "imagePullPolicy": "Always", |
420 | 178 | 'ports': [{'containerPort': 2160, 'protocol': 'TCP'}], | 178 | "ports": [{"containerPort": 2160, "protocol": "TCP"}], |
421 | 179 | 'envConfig': {'MM_PD_BOT_CFG': get_cfg_content('good_configuration')}, | 179 | "envConfig": {"MM_PD_BOT_CFG": get_cfg_content("good_configuration")}, |
422 | 180 | } | 180 | } |
423 | 181 | ], | 181 | ], |
426 | 182 | 'kubernetesResources': { | 182 | "kubernetesResources": { |
427 | 183 | 'ingressResources': [ | 183 | "ingressResources": [ |
428 | 184 | { | 184 | { |
432 | 185 | 'name': 'mm-pd-bot-ingress', | 185 | "name": "mm-pd-bot-ingress", |
433 | 186 | 'spec': { | 186 | "spec": { |
434 | 187 | 'rules': [ | 187 | "rules": [ |
435 | 188 | { | 188 | { |
439 | 189 | 'host': 'mm-pd-bot.example.com', | 189 | "host": "mm-pd-bot.example.com", |
440 | 190 | 'http': { | 190 | "http": { |
441 | 191 | 'paths': [ | 191 | "paths": [ |
442 | 192 | { | 192 | { |
445 | 193 | 'path': '/bdddcacb-ab42-40ac-9106-4275c1db1519/', | 193 | "path": "/bdddcacb-ab42-40ac-9106-4275c1db1519/", |
446 | 194 | 'backend': {'serviceName': 'mm-pd-bot', 'servicePort': 2160}, | 194 | "backend": {"serviceName": "mm-pd-bot", "servicePort": 2160}, |
447 | 195 | }, | 195 | }, |
448 | 196 | ], | 196 | ], |
449 | 197 | }, | 197 | }, |
450 | 198 | }, | 198 | }, |
451 | 199 | ], | 199 | ], |
452 | 200 | }, | 200 | }, |
454 | 201 | 'annotations': {'nginx.ingress.kubernetes.io/ssl-redirect': 'false'}, | 201 | "annotations": {"nginx.ingress.kubernetes.io/ssl-redirect": "false"}, |
455 | 202 | }, | 202 | }, |
456 | 203 | ], | 203 | ], |
457 | 204 | }, | 204 | }, |
458 | 205 | }, | 205 | }, |
459 | 206 | }, | 206 | }, |
466 | 207 | 'ssl': { | 207 | "ssl": { |
467 | 208 | 'config': { | 208 | "config": { |
468 | 209 | 'image_path': 'mm_pd_bot:devel', | 209 | "image_path": "mm_pd_bot:devel", |
469 | 210 | 'mm_pd_bot_cfg': get_cfg_content('ssl_configuration'), | 210 | "mm_pd_bot_cfg": get_cfg_content("ssl_configuration"), |
470 | 211 | 'ingress_whitelist_source_range': '10.0.69.0/24', | 211 | "ingress_whitelist_source_range": "10.0.69.0/24", |
471 | 212 | 'tls_secret_name': 'mm_pd_bot_secret', | 212 | "tls_secret_name": "mm_pd_bot_secret", |
472 | 213 | }, | 213 | }, |
476 | 214 | 'pod_spec': { | 214 | "pod_spec": { |
477 | 215 | 'version': 3, # otherwise resources are ignored | 215 | "version": 3, # otherwise resources are ignored |
478 | 216 | 'containers': [ | 216 | "containers": [ |
479 | 217 | { | 217 | { |
485 | 218 | 'name': 'mm-pd-bot', | 218 | "name": "mm-pd-bot", |
486 | 219 | 'imageDetails': {'imagePath': 'mm_pd_bot:devel'}, | 219 | "imageDetails": {"imagePath": "mm_pd_bot:devel"}, |
487 | 220 | 'imagePullPolicy': 'Always', | 220 | "imagePullPolicy": "Always", |
488 | 221 | 'ports': [{'containerPort': 2160, 'protocol': 'TCP'}], | 221 | "ports": [{"containerPort": 2160, "protocol": "TCP"}], |
489 | 222 | 'envConfig': {'MM_PD_BOT_CFG': get_cfg_content('ssl_configuration')}, | 222 | "envConfig": {"MM_PD_BOT_CFG": get_cfg_content("ssl_configuration")}, |
490 | 223 | } | 223 | } |
491 | 224 | ], | 224 | ], |
494 | 225 | 'kubernetesResources': { | 225 | "kubernetesResources": { |
495 | 226 | 'ingressResources': [ | 226 | "ingressResources": [ |
496 | 227 | { | 227 | { |
500 | 228 | 'name': 'mm-pd-bot-ingress', | 228 | "name": "mm-pd-bot-ingress", |
501 | 229 | 'spec': { | 229 | "spec": { |
502 | 230 | 'rules': [ | 230 | "rules": [ |
503 | 231 | { | 231 | { |
507 | 232 | 'host': 'mm-pd-bot.example.com', | 232 | "host": "mm-pd-bot.example.com", |
508 | 233 | 'http': { | 233 | "http": { |
509 | 234 | 'paths': [ | 234 | "paths": [ |
510 | 235 | { | 235 | { |
513 | 236 | 'path': '/bdddcacb-ab42-40ac-9106-4275c1db1519/', | 236 | "path": "/bdddcacb-ab42-40ac-9106-4275c1db1519/", |
514 | 237 | 'backend': {'serviceName': 'mm-pd-bot', 'servicePort': 2160}, | 237 | "backend": {"serviceName": "mm-pd-bot", "servicePort": 2160}, |
515 | 238 | }, | 238 | }, |
516 | 239 | ], | 239 | ], |
517 | 240 | }, | 240 | }, |
518 | 241 | }, | 241 | }, |
519 | 242 | ], | 242 | ], |
521 | 243 | 'tls': [{'hosts': ['mm-pd-bot.example.com'], 'secretName': 'mm_pd_bot_secret'}], | 243 | "tls": [{"hosts": ["mm-pd-bot.example.com"], "secretName": "mm_pd_bot_secret"}], |
522 | 244 | }, | 244 | }, |
524 | 245 | 'annotations': {'nginx.ingress.kubernetes.io/whitelist-source-range': '10.0.69.0/24'}, | 245 | "annotations": {"nginx.ingress.kubernetes.io/whitelist-source-range": "10.0.69.0/24"}, |
525 | 246 | }, | 246 | }, |
526 | 247 | ], | 247 | ], |
527 | 248 | }, | 248 | }, |
528 | 249 | }, | 249 | }, |
529 | 250 | }, | 250 | }, |
535 | 251 | 'ssl_without_whitelist': { | 251 | "ssl_without_whitelist": { |
536 | 252 | 'config': { | 252 | "config": { |
537 | 253 | 'image_path': 'mm_pd_bot:devel', | 253 | "image_path": "mm_pd_bot:devel", |
538 | 254 | 'mm_pd_bot_cfg': get_cfg_content('ssl_configuration'), | 254 | "mm_pd_bot_cfg": get_cfg_content("ssl_configuration"), |
539 | 255 | 'tls_secret_name': 'mm_pd_bot_secret', | 255 | "tls_secret_name": "mm_pd_bot_secret", |
540 | 256 | }, | 256 | }, |
544 | 257 | 'pod_spec': { | 257 | "pod_spec": { |
545 | 258 | 'version': 3, # otherwise resources are ignored | 258 | "version": 3, # otherwise resources are ignored |
546 | 259 | 'containers': [ | 259 | "containers": [ |
547 | 260 | { | 260 | { |
553 | 261 | 'name': 'mm-pd-bot', | 261 | "name": "mm-pd-bot", |
554 | 262 | 'imageDetails': {'imagePath': 'mm_pd_bot:devel'}, | 262 | "imageDetails": {"imagePath": "mm_pd_bot:devel"}, |
555 | 263 | 'imagePullPolicy': 'Always', | 263 | "imagePullPolicy": "Always", |
556 | 264 | 'ports': [{'containerPort': 2160, 'protocol': 'TCP'}], | 264 | "ports": [{"containerPort": 2160, "protocol": "TCP"}], |
557 | 265 | 'envConfig': {'MM_PD_BOT_CFG': get_cfg_content('ssl_configuration')}, | 265 | "envConfig": {"MM_PD_BOT_CFG": get_cfg_content("ssl_configuration")}, |
558 | 266 | } | 266 | } |
559 | 267 | ], | 267 | ], |
562 | 268 | 'kubernetesResources': { | 268 | "kubernetesResources": { |
563 | 269 | 'ingressResources': [ | 269 | "ingressResources": [ |
564 | 270 | { | 270 | { |
568 | 271 | 'name': 'mm-pd-bot-ingress', | 271 | "name": "mm-pd-bot-ingress", |
569 | 272 | 'spec': { | 272 | "spec": { |
570 | 273 | 'rules': [ | 273 | "rules": [ |
571 | 274 | { | 274 | { |
575 | 275 | 'host': 'mm-pd-bot.example.com', | 275 | "host": "mm-pd-bot.example.com", |
576 | 276 | 'http': { | 276 | "http": { |
577 | 277 | 'paths': [ | 277 | "paths": [ |
578 | 278 | { | 278 | { |
581 | 279 | 'path': '/bdddcacb-ab42-40ac-9106-4275c1db1519/', | 279 | "path": "/bdddcacb-ab42-40ac-9106-4275c1db1519/", |
582 | 280 | 'backend': {'serviceName': 'mm-pd-bot', 'servicePort': 2160}, | 280 | "backend": {"serviceName": "mm-pd-bot", "servicePort": 2160}, |
583 | 281 | }, | 281 | }, |
584 | 282 | ], | 282 | ], |
585 | 283 | }, | 283 | }, |
586 | 284 | }, | 284 | }, |
587 | 285 | ], | 285 | ], |
589 | 286 | 'tls': [{'hosts': ['mm-pd-bot.example.com'], 'secretName': 'mm_pd_bot_secret'}], | 286 | "tls": [{"hosts": ["mm-pd-bot.example.com"], "secretName": "mm_pd_bot_secret"}], |
590 | 287 | }, | 287 | }, |
591 | 288 | }, | 288 | }, |
592 | 289 | ], | 289 | ], |
593 | diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py | |||
594 | index 27bbaf3..d56fcde 100755 | |||
595 | --- a/tests/unit/test_charm.py | |||
596 | +++ b/tests/unit/test_charm.py | |||
597 | @@ -39,8 +39,8 @@ class TestMmPdBotK8sCharmBlockedStatus(unittest.TestCase): | |||
598 | 39 | """Cleanup the harness.""" | 39 | """Cleanup the harness.""" |
599 | 40 | self.harness.cleanup() | 40 | self.harness.cleanup() |
600 | 41 | 41 | ||
603 | 42 | @patch('charm.MmPdBotK8sCharm._validate_mm_pd_bot_configuration') | 42 | @patch("charm.MmPdBotK8sCharm._validate_mm_pd_bot_configuration") |
604 | 43 | @patch('charm.MmPdBotK8sCharm._check_juju_settings') | 43 | @patch("charm.MmPdBotK8sCharm._check_juju_settings") |
605 | 44 | def test_check_for_config_problems(self, mock_juju, mock_mm_pd_bot): | 44 | def test_check_for_config_problems(self, mock_juju, mock_mm_pd_bot): |
606 | 45 | """Check the calls for config problems.""" | 45 | """Check the calls for config problems.""" |
607 | 46 | self.harness.charm._check_for_config_problems() | 46 | self.harness.charm._check_for_config_problems() |
608 | @@ -51,47 +51,47 @@ class TestMmPdBotK8sCharmBlockedStatus(unittest.TestCase): | |||
609 | 51 | """Check the required juju settings.""" | 51 | """Check the required juju settings.""" |
610 | 52 | for scenario, values in TEST_JUJU_SETTINGS.items(): | 52 | for scenario, values in TEST_JUJU_SETTINGS.items(): |
611 | 53 | with self.subTest(scenario=scenario): | 53 | with self.subTest(scenario=scenario): |
613 | 54 | with self.assertLogs(level='ERROR') as logger: | 54 | with self.assertLogs(level="ERROR") as logger: |
614 | 55 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: | 55 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: |
615 | 56 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # Load the default values | 56 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # Load the default values |
617 | 57 | self.harness.update_config(values['config']) | 57 | self.harness.update_config(values["config"]) |
618 | 58 | self.harness.charm._check_juju_settings() | 58 | self.harness.charm._check_juju_settings() |
621 | 59 | self.assertEqual(sorted(logger.output), sorted(values['logger'])) | 59 | self.assertEqual(sorted(logger.output), sorted(values["logger"])) |
622 | 60 | self.assertEqual(str(exc.exception), values['expected']) | 60 | self.assertEqual(str(exc.exception), values["expected"]) |
623 | 61 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 61 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
624 | 62 | 62 | ||
625 | 63 | def test_validate_mm_pd_bot_configuration(self): | 63 | def test_validate_mm_pd_bot_configuration(self): |
626 | 64 | """Check the MM_PD_BOT_CFG string is a valid INI.""" | 64 | """Check the MM_PD_BOT_CFG string is a valid INI.""" |
627 | 65 | for scenario, values in VALIDATE_MM_PD_BOT_CFG.items(): | 65 | for scenario, values in VALIDATE_MM_PD_BOT_CFG.items(): |
628 | 66 | with self.subTest(scenario=scenario): | 66 | with self.subTest(scenario=scenario): |
631 | 67 | self.harness.update_config(values['config']) | 67 | self.harness.update_config(values["config"]) |
632 | 68 | if values['expected'] is True: | 68 | if values["expected"] is True: |
633 | 69 | self.harness.charm._validate_mm_pd_bot_configuration() | 69 | self.harness.charm._validate_mm_pd_bot_configuration() |
634 | 70 | else: | 70 | else: |
636 | 71 | with self.assertLogs(level='ERROR') as logger: | 71 | with self.assertLogs(level="ERROR") as logger: |
637 | 72 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: | 72 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: |
638 | 73 | self.harness.charm._validate_mm_pd_bot_configuration() | 73 | self.harness.charm._validate_mm_pd_bot_configuration() |
641 | 74 | self.assertEqual(str(exc.exception), values['expected']) | 74 | self.assertEqual(str(exc.exception), values["expected"]) |
642 | 75 | self.assertEqual(sorted(logger.output), sorted(values['logger'])) | 75 | self.assertEqual(sorted(logger.output), sorted(values["logger"])) |
643 | 76 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 76 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
644 | 77 | 77 | ||
645 | 78 | def test_load_mm_pd_bot_configuration(self): | 78 | def test_load_mm_pd_bot_configuration(self): |
646 | 79 | """Test the loading of the configuration for the bot.""" | 79 | """Test the loading of the configuration for the bot.""" |
648 | 80 | config = VALIDATE_MM_PD_BOT_CFG['good_configuration']['config']['mm_pd_bot_cfg'] | 80 | config = VALIDATE_MM_PD_BOT_CFG["good_configuration"]["config"]["mm_pd_bot_cfg"] |
649 | 81 | loaded_config = self.harness.charm._load_mm_pd_bot_configuration(config) | 81 | loaded_config = self.harness.charm._load_mm_pd_bot_configuration(config) |
650 | 82 | self.assertIsInstance(loaded_config, configparser.ConfigParser) | 82 | self.assertIsInstance(loaded_config, configparser.ConfigParser) |
651 | 83 | 83 | ||
653 | 84 | config = VALIDATE_MM_PD_BOT_CFG['bad_formatted_configuration']['config']['mm_pd_bot_cfg'] | 84 | config = VALIDATE_MM_PD_BOT_CFG["bad_formatted_configuration"]["config"]["mm_pd_bot_cfg"] |
654 | 85 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: | 85 | with self.assertRaises(MmPdBotK8sCharmConfigError) as exc: |
655 | 86 | loaded_config = self.harness.charm._load_mm_pd_bot_configuration(config) | 86 | loaded_config = self.harness.charm._load_mm_pd_bot_configuration(config) |
657 | 87 | self.assertEqual(str(exc.exception), VALIDATE_MM_PD_BOT_CFG['bad_formatted_configuration']['expected']) | 87 | self.assertEqual(str(exc.exception), VALIDATE_MM_PD_BOT_CFG["bad_formatted_configuration"]["expected"]) |
658 | 88 | 88 | ||
659 | 89 | def test_configure_pod(self): | 89 | def test_configure_pod(self): |
660 | 90 | """Test the pod configuration.""" | 90 | """Test the pod configuration.""" |
661 | 91 | mock_event = MagicMock() | 91 | mock_event = MagicMock() |
662 | 92 | 92 | ||
663 | 93 | # Good configuration but not leader | 93 | # Good configuration but not leader |
665 | 94 | self.harness.update_config(VALIDATE_MM_PD_BOT_CFG['good_configuration']['config']) | 94 | self.harness.update_config(VALIDATE_MM_PD_BOT_CFG["good_configuration"]["config"]) |
666 | 95 | self.harness.set_leader(False) | 95 | self.harness.set_leader(False) |
667 | 96 | self.harness.charm.unit.status = BlockedStatus("Testing") | 96 | self.harness.charm.unit.status = BlockedStatus("Testing") |
668 | 97 | self.harness.charm.configure_pod(mock_event) | 97 | self.harness.charm.configure_pod(mock_event) |
669 | @@ -99,11 +99,11 @@ class TestMmPdBotK8sCharmBlockedStatus(unittest.TestCase): | |||
670 | 99 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 99 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
671 | 100 | 100 | ||
672 | 101 | # Good configuration and leader | 101 | # Good configuration and leader |
674 | 102 | self.harness.update_config(VALIDATE_MM_PD_BOT_CFG['good_configuration']['config']) | 102 | self.harness.update_config(VALIDATE_MM_PD_BOT_CFG["good_configuration"]["config"]) |
675 | 103 | self.harness.set_leader(True) | 103 | self.harness.set_leader(True) |
676 | 104 | self.harness.charm.unit.status = BlockedStatus("Testing") | 104 | self.harness.charm.unit.status = BlockedStatus("Testing") |
677 | 105 | self.harness.charm.configure_pod(mock_event) | 105 | self.harness.charm.configure_pod(mock_event) |
679 | 106 | with self.assertLogs(level='INFO') as logger: | 106 | with self.assertLogs(level="INFO") as logger: |
680 | 107 | self.harness.charm.configure_pod(mock_event) | 107 | self.harness.charm.configure_pod(mock_event) |
681 | 108 | self.assertEqual( | 108 | self.assertEqual( |
682 | 109 | sorted(logger.output), | 109 | sorted(logger.output), |
683 | @@ -113,8 +113,8 @@ class TestMmPdBotK8sCharmBlockedStatus(unittest.TestCase): | |||
684 | 113 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 113 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
685 | 114 | 114 | ||
686 | 115 | # Bad configuration and leader | 115 | # Bad configuration and leader |
689 | 116 | config = VALIDATE_MM_PD_BOT_CFG['bad_formatted_configuration']['config'] | 116 | config = VALIDATE_MM_PD_BOT_CFG["bad_formatted_configuration"]["config"] |
690 | 117 | expected = VALIDATE_MM_PD_BOT_CFG['bad_formatted_configuration']['expected'] | 117 | expected = VALIDATE_MM_PD_BOT_CFG["bad_formatted_configuration"]["expected"] |
691 | 118 | self.harness.update_config(config) | 118 | self.harness.update_config(config) |
692 | 119 | self.harness.set_leader(True) | 119 | self.harness.set_leader(True) |
693 | 120 | self.harness.charm.configure_pod(mock_event) | 120 | self.harness.charm.configure_pod(mock_event) |
694 | @@ -125,26 +125,26 @@ class TestMmPdBotK8sCharmBlockedStatus(unittest.TestCase): | |||
695 | 125 | """Check the crafting of the pod spec.""" | 125 | """Check the crafting of the pod spec.""" |
696 | 126 | for scenario, values in VALIDATE_POD_SPEC.items(): | 126 | for scenario, values in VALIDATE_POD_SPEC.items(): |
697 | 127 | with self.subTest(scenario=scenario): | 127 | with self.subTest(scenario=scenario): |
699 | 128 | self.harness.update_config(values['config']) | 128 | self.harness.update_config(values["config"]) |
700 | 129 | self.harness.charm.bot_config = self.harness.charm._load_mm_pd_bot_configuration( | 129 | self.harness.charm.bot_config = self.harness.charm._load_mm_pd_bot_configuration( |
702 | 130 | values['config']['mm_pd_bot_cfg'] | 130 | values["config"]["mm_pd_bot_cfg"] |
703 | 131 | ) | 131 | ) |
705 | 132 | self.assertEqual(self.harness.charm._make_pod_spec(), values['pod_spec']) | 132 | self.assertEqual(self.harness.charm._make_pod_spec(), values["pod_spec"]) |
706 | 133 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 133 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
707 | 134 | 134 | ||
708 | 135 | def test_update_pod_spec_for_k8s_ingress(self): | 135 | def test_update_pod_spec_for_k8s_ingress(self): |
709 | 136 | """Check the crafting of the ingress part of the pod spec.""" | 136 | """Check the crafting of the ingress part of the pod spec.""" |
710 | 137 | for scenario, values in VALIDATE_POD_SPEC_AND_INGRESS.items(): | 137 | for scenario, values in VALIDATE_POD_SPEC_AND_INGRESS.items(): |
711 | 138 | with self.subTest(scenario=scenario): | 138 | with self.subTest(scenario=scenario): |
713 | 139 | self.harness.update_config(values['config']) | 139 | self.harness.update_config(values["config"]) |
714 | 140 | self.harness.charm.bot_config = self.harness.charm._load_mm_pd_bot_configuration( | 140 | self.harness.charm.bot_config = self.harness.charm._load_mm_pd_bot_configuration( |
716 | 141 | values['config']['mm_pd_bot_cfg'] | 141 | values["config"]["mm_pd_bot_cfg"] |
717 | 142 | ) | 142 | ) |
718 | 143 | pod_spec = self.harness.charm._make_pod_spec() | 143 | pod_spec = self.harness.charm._make_pod_spec() |
719 | 144 | self.harness.charm._update_pod_spec_for_k8s_ingress(pod_spec) | 144 | self.harness.charm._update_pod_spec_for_k8s_ingress(pod_spec) |
721 | 145 | self.assertEqual(pod_spec, values['pod_spec']) | 145 | self.assertEqual(pod_spec, values["pod_spec"]) |
722 | 146 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run | 146 | self.harness.update_config(JUJU_SETTINGS_DEFAULT) # You need to clean the config after each run |
723 | 147 | 147 | ||
724 | 148 | 148 | ||
726 | 149 | if __name__ == '__main__': | 149 | if __name__ == "__main__": |
727 | 150 | unittest.main() | 150 | unittest.main() |
+1