Merge ~woutervb/various/+git/snapstore-proxy-charm:status_action_test_refactor into ~woutervb/various/+git/snapstore-proxy-charm:main

Proposed by Wouter van Bommel
Status: Merged
Merged at revision: c78345aa91fe7b80e2d935ec334eaeb5409d8a9e
Proposed branch: ~woutervb/various/+git/snapstore-proxy-charm:status_action_test_refactor
Merge into: ~woutervb/various/+git/snapstore-proxy-charm:main
Prerequisite: ~woutervb/various/+git/snapstore-proxy-charm:freeze_after_registration
Diff against target: 219 lines (+78/-6)
7 files modified
Makefile (+1/-1)
README.md (+5/-1)
actions.yaml (+4/-1)
src/charm.py (+11/-0)
src/resource_helpers.py (+7/-0)
tests/test_charm.py (+32/-2)
tests/test_resource_helpers.py (+18/-1)
Reviewer Review Type Date Requested Status
Przemysław Suliga (community) Approve
Wouter van Bommel Pending
Review via email: mp+412990@code.launchpad.net

Commit message

Added status action and refactored test

Refactored test of the charm in logical subsets, to ease expansion and
keep grouped tests together.

Added an status action, that will return the result of the proxy status
command.

To post a comment you must log in.
Revision history for this message
Przemysław Suliga (suligap) wrote :

One comment

Revision history for this message
Wouter van Bommel (woutervb) wrote :

Added a reply.
Again, did a rebase etc to things make sense

Revision history for this message
Przemysław Suliga (suligap) wrote :

Thanks, +1 with a reply to the comment.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/Makefile b/Makefile
index 24a72d4..bcd2827 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ CHARMCRAFT = $(shell which charmcraft)
8# Releases should match the run-on section in charmcraft.yaml in the same order8# Releases should match the run-on section in charmcraft.yaml in the same order
9RELEASES = 20.04 18.049RELEASES = 20.04 18.04
10CHARM_FILENAME = $(CHARM_NAME)$(subst $(noop) $(noop),,$(addsuffix -amd64, $(addprefix _ubuntu-, $(RELEASES)))).charm10CHARM_FILENAME = $(CHARM_NAME)$(subst $(noop) $(noop),,$(addsuffix -amd64, $(addprefix _ubuntu-, $(RELEASES)))).charm
11DEPS = $(shell find src -name '*.py') requirements.txt11DEPS = $(shell find src -name '*.py') requirements.txt actions.yaml config.yaml
1212
13.PHONY: charm13.PHONY: charm
14charm: $(CHARM_FILENAME)14charm: $(CHARM_FILENAME)
diff --git a/README.md b/README.md
index d3157fb..7881848 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,15 @@ This charm will allow the installation and management of the snapstore proxy cha
66
7## Usage7## Usage
88
9Minimal items that have to be set are an username / password, on ubuntu onethat correspond to an account that does not have 2fa enabled, and has accepted the developer agreement on snapstore.io.9Minimal items that have to be set are the domain this proxy runs on, and a username / password, on ubuntu one that correspond to an account that does not have 2fa enabled, and has accepted the developer agreement on snapstore.io.
1010
1111
12## Relations12## Relations
1313
14This charm depends on a postgresql database, so this charm should relate to a porgresql database, before anything else can be done.14This charm depends on a postgresql database, so this charm should relate to a porgresql database, before anything else can be done.
1515
16## Actions
1617
18The charm supports the following actions:
19
20 * status - Get the status result of the proxy, use like; `juju run-action snapstore-proxy/leader status --wait`
diff --git a/actions.yaml b/actions.yaml
index 1e74ed1..d97efbd 100644
--- a/actions.yaml
+++ b/actions.yaml
@@ -2,5 +2,8 @@
2# See LICENSE file for licensing details.2# See LICENSE file for licensing details.
3#3#
4# Learn more about actions at: https://juju.is/docs/sdk/actions4# Learn more about actions at: https://juju.is/docs/sdk/actions
55status:
6 description: |
7 Get the status of the proxy services, ie
8 juju run-action snapstore-proxy/leader status --wait
69
diff --git a/src/charm.py b/src/charm.py
index b82eac9..419643a 100755
--- a/src/charm.py
+++ b/src/charm.py
@@ -20,6 +20,7 @@ from helpers import all_config_options, configure_proxy, default_values
20from optionvalidation import OptionValidation20from optionvalidation import OptionValidation
21from resource_helpers import (21from resource_helpers import (
22 create_database,22 create_database,
23 get_status,
23 install_from_the_charmstore,24 install_from_the_charmstore,
24 register_store,25 register_store,
25 snap_details,26 snap_details,
@@ -58,6 +59,9 @@ class SnapstoreProxyCharm(CharmBase):
58 self.db.on.database_relation_broken, self._on_database_relation_broken59 self.db.on.database_relation_broken, self._on_database_relation_broken
59 )60 )
6061
62 # Actions
63 self.framework.observe(self.on.status_action, self._on_status_action)
64
61 def _on_config_changed(self, event):65 def _on_config_changed(self, event):
62 """Handle update on the configuration of the proxy.66 """Handle update on the configuration of the proxy.
6367
@@ -303,6 +307,13 @@ class SnapstoreProxyCharm(CharmBase):
303307
304 self.evaluate_status()308 self.evaluate_status()
305309
310 def _on_status_action(self, event):
311 output, exitcode = get_status()
312 if exitcode == 0:
313 event.set_results({"result": output})
314 else:
315 event.fail(f"Failed to get status, errorcode {exitcode}\n, result {output}")
316
306317
307if __name__ == "__main__":318if __name__ == "__main__":
308 main(SnapstoreProxyCharm)319 main(SnapstoreProxyCharm)
diff --git a/src/resource_helpers.py b/src/resource_helpers.py
index 09cddc9..e5e9e76 100644
--- a/src/resource_helpers.py
+++ b/src/resource_helpers.py
@@ -45,3 +45,10 @@ def register_store(username, password):
45def create_database(uri):45def create_database(uri):
46 """Let the proxy configure the database."""46 """Let the proxy configure the database."""
47 run(["/snap/bin/snap-store-proxy", "create-database", uri])47 run(["/snap/bin/snap-store-proxy", "create-database", uri])
48
49
50def get_status():
51 """Return the status result and exitcode"""
52 result = run(["/snap/bin/snap-store-proxy", "status"], capture_output=True)
53
54 return result.stdout.decode("utf-8"), result.returncode
diff --git a/tests/test_charm.py b/tests/test_charm.py
index 6f58424..f89e6a0 100644
--- a/tests/test_charm.py
+++ b/tests/test_charm.py
@@ -18,7 +18,7 @@ import exceptions
18from charm import DATABASE_NAME, SnapstoreProxyCharm18from charm import DATABASE_NAME, SnapstoreProxyCharm
1919
2020
21class TestCharm:21class CharmTest:
22 def setup_method(self):22 def setup_method(self):
23 self.harness = Harness(SnapstoreProxyCharm)23 self.harness = Harness(SnapstoreProxyCharm)
24 self.harness.begin()24 self.harness.begin()
@@ -32,6 +32,8 @@ class TestCharm:
32 def teardown_method(self):32 def teardown_method(self):
33 self.harness.cleanup()33 self.harness.cleanup()
3434
35
36class TestConfig(CharmTest):
35 def test_default_config_values(self):37 def test_default_config_values(self):
36 # Our implicit requirement is that the database uri has been set.38 # Our implicit requirement is that the database uri has been set.
37 self.harness.charm._stored.db_uri = "postgresql://fake/database"39 self.harness.charm._stored.db_uri = "postgresql://fake/database"
@@ -156,6 +158,8 @@ class TestCharm:
156 assert patched_proxy.called158 assert patched_proxy.called
157 patched_proxy.assert_called_once_with(None)159 patched_proxy.assert_called_once_with(None)
158160
161
162class TestStatus(CharmTest):
159 def test_status_missing_db_uri(self):163 def test_status_missing_db_uri(self):
160 self.harness.charm._stored.db_uri = None164 self.harness.charm._stored.db_uri = None
161165
@@ -211,6 +215,8 @@ class TestCharm:
211215
212 assert self.harness.charm.unit.status.message == ""216 assert self.harness.charm.unit.status.message == ""
213217
218
219class TestEvents(CharmTest):
214 def test_on_update_status(self):220 def test_on_update_status(self):
215 self.harness.disable_hooks()221 self.harness.disable_hooks()
216 self.harness.set_leader(True)222 self.harness.set_leader(True)
@@ -304,6 +310,28 @@ class TestCharm:
304 assert self.harness.charm._stored.db_uri is None310 assert self.harness.charm._stored.db_uri is None
305 patched_evaluate_status.assert_called_once_with()311 patched_evaluate_status.assert_called_once_with()
306312
313 def test_on_status_action_succeeds(self):
314 event = MagicMock()
315 with patch("charm.get_status") as patched_get_status:
316 patched_get_status.return_value = ("String", 0)
317 self.harness.charm._on_status_action(event)
318
319 patched_get_status.assert_called_once_with()
320 event.set_results.assert_called_once_with({"result": "String"})
321
322 def test_on_status_action_fails(self):
323 event = MagicMock()
324 with patch("charm.get_status") as patched_get_status:
325 patched_get_status.return_value = ("String", 1)
326 self.harness.charm._on_status_action(event)
327
328 patched_get_status.assert_called_once_with()
329 event.fail.assert_called_once_with(
330 "Failed to get status, result String, errorcode 1"
331 )
332
333
334class TestRegistration(CharmTest):
307 def test_handle_registration_no_database(self, caplog):335 def test_handle_registration_no_database(self, caplog):
308 caplog.clear()336 caplog.clear()
309 caplog.set_level(logging.INFO)337 caplog.set_level(logging.INFO)
@@ -397,6 +425,8 @@ class TestCharm:
397 == "Failed to register, check logging to find the reason"425 == "Failed to register, check logging to find the reason"
398 )426 )
399427
428
429class TestSanity(CharmTest):
400 def test_empty_username_after_registration_and_active_status(self):430 def test_empty_username_after_registration_and_active_status(self):
401 self.harness.charm._stored.registered = True431 self.harness.charm._stored.registered = True
402 self.harness.charm._stored.username = "Some value"432 self.harness.charm._stored.username = "Some value"
@@ -409,7 +439,7 @@ class TestCharm:
409 assert self.harness.charm._stored.username == "Some value"439 assert self.harness.charm._stored.username == "Some value"
410 assert self.harness.charm.unit.status == ActiveStatus("")440 assert self.harness.charm.unit.status == ActiveStatus("")
411441
412 def test_empty_password(self):442 def test_empty_password_after_registration_and_active_status(self):
413 self.harness.charm._stored.registered = True443 self.harness.charm._stored.registered = True
414 self.harness.charm._stored.password = "Some value"444 self.harness.charm._stored.password = "Some value"
415 self.harness.charm._stored.db_uri = "postgresql://user@host/database"445 self.harness.charm._stored.db_uri = "postgresql://user@host/database"
diff --git a/tests/test_resource_helpers.py b/tests/test_resource_helpers.py
index eaf5b22..1db2005 100644
--- a/tests/test_resource_helpers.py
+++ b/tests/test_resource_helpers.py
@@ -1,6 +1,6 @@
1import logging1import logging
2from subprocess import PIPE, CalledProcessError2from subprocess import PIPE, CalledProcessError
3from unittest.mock import patch3from unittest.mock import MagicMock, patch
44
5import resource_helpers5import resource_helpers
66
@@ -82,3 +82,20 @@ def test_create_database():
82 patched_run.assert_called_once_with(82 patched_run.assert_called_once_with(
83 ["/snap/bin/snap-store-proxy", "create-database", test_dsn]83 ["/snap/bin/snap-store-proxy", "create-database", test_dsn]
84 )84 )
85
86
87def test_get_status():
88 result = MagicMock()
89 result.returncode = 10
90 result.stdout = "My magic result".encode("utf-8")
91
92 with patch("resource_helpers.run") as patched_run:
93 patched_run.return_value = result
94 output, exitcode = resource_helpers.get_status()
95
96 assert patched_run.called
97 patched_run.assert_called_once_with(
98 ["/snap/bin/snap-store-proxy", "status"], capture_output=True
99 )
100 assert exitcode == 10
101 assert output == "My magic result"

Subscribers

People subscribed via source and target branches

to all changes: