Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport ErrorStatus fix #927

Merged
merged 1 commit into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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