Skip to content

Commit

Permalink
Add ErrorStatus (canonical#875)
Browse files Browse the repository at this point in the history
Add ErrorStatus so that getting Unit/App.status when the status is
"error" does not raise.

Co-authored-by: Ben Hoyt <ben.hoyt@canonical.com>
  • Loading branch information
2 people authored and mkalcok committed Apr 25, 2023
1 parent 7afd45d commit fe7e40c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
10 changes: 10 additions & 0 deletions ops/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,16 @@ def __repr__(self):
return "UnknownStatus()"


@StatusBase.register
class ErrorStatus(StatusBase):
"""The unit status is error.
The unit-agent has encountered an error (the application or unit requires
human intervention in order to operate correctly).
"""
name = 'error'


@StatusBase.register
class ActiveStatus(StatusBase):
"""The unit is ready.
Expand Down
47 changes: 46 additions & 1 deletion test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2283,7 +2283,7 @@ def test_status_is_app_forced_kwargs(self):
case()

def test_local_set_invalid_status(self):
# juju return exit code 1 if you ask to set status to 'unknown'
# juju returns exit code 1 if you ask to set status to 'unknown' or 'error'
meta = ops.charm.CharmMeta.from_yaml('''
name: myapp
''')
Expand All @@ -2293,20 +2293,65 @@ def test_local_set_invalid_status(self):

with self.assertRaises(ops.model.ModelError):
model.unit.status = ops.model.UnknownStatus()
with self.assertRaises(ops.model.ModelError):
model.unit.status = ops.model.ErrorStatus()

self.assertEqual(fake_script_calls(self, True), [
['status-set', '--application=False', 'unknown', ''],
['status-set', '--application=False', 'error', ''],
])

with self.assertRaises(ops.model.ModelError):
model.app.status = ops.model.UnknownStatus()
with self.assertRaises(ops.model.ModelError):
model.app.status = ops.model.ErrorStatus()

# A leadership check is needed for application status.
self.assertEqual(fake_script_calls(self, True), [
['is-leader', '--format=json'],
['status-set', '--application=True', 'unknown', ''],
['status-set', '--application=True', 'error', ''],
])

def test_local_get_status(self):
for name, expected_cls in (
("active", ops.model.ActiveStatus),
("waiting", ops.model.WaitingStatus),
("blocked", ops.model.BlockedStatus),
("maintenance", ops.model.MaintenanceStatus),
("error", ops.model.ErrorStatus),
):
meta = ops.charm.CharmMeta.from_yaml('''
name: myapp
''')
model = ops.model.Model(meta, self.backend)

with self.subTest(name):
content = json.dumps({
"message": "foo",
"status": name,
"status-data": {},
})
fake_script(self, 'status-get', "echo '{}'".format(content))

self.assertIsInstance(model.unit.status, expected_cls)
self.assertEqual(model.unit.status.name, name)
self.assertEqual(model.unit.status.message, "foo")

content = json.dumps({
"application-status": {
"message": "bar",
"status": name,
"status-data": {},
}
})
fake_script(self, 'status-get', "echo '{}'".format(content))
fake_script(self, 'is-leader', 'echo true')

self.assertIsInstance(model.app.status, expected_cls)
self.assertEqual(model.app.status.name, name)
self.assertEqual(model.app.status.message, "bar")

def test_status_set_is_app_not_bool_raises(self):
for is_app_v in [None, 1, 2.0, 'a', b'beef', object]:
with self.assertRaises(TypeError):
Expand Down

0 comments on commit fe7e40c

Please sign in to comment.