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

Fix unit.run to support Juju 2.9 and 3.x #655

Merged

Conversation

rgildein
Copy link
Contributor

The run_on_unit require to be awaited for juju 3+, and this fix proposes a solution to check status of action and wait for it if it's "pending". This was original described in issue #649 and marked as fixed by #650, however the action object is never awaitable as it can be seen in my examples below.

I tested in with this script

import asyncio
import inspect
from juju.model import Model

async def run_test_command():
    model = Model()
    await model.connect(model_name="test")
    # try to run command
    try:
        action = await model.units["grafana/0"].run("echo HelloWord")
        print("command isawaitable: ", inspect.isawaitable(action))
        print("command action.data: ", action.data)
        print("command action.status: ", action.status)
        print("command action.results: ", action.results)
        if action.status == "pending":
            await action.wait()
        print("command isawaitable: ", inspect.isawaitable(action))
        print("command action.data: ", action.data)
        print("command action.status: ", action.status)
        print("command action.results: ", action.results)
    except Exception as error:
        print(error)
    # try to run actions get-admin-password
    try:
        action = await model.units["grafana/0"].run("actions/get-admin-password")  # `actions/` needs to be specified in Juju 2.9
        print("command isawaitable: ", inspect.isawaitable(action))
        print("command action.data: ", action.data)
        print("command action.status: ", action.status)
        print("command action.results: ", action.results)
        if action.status == "pending":
            await action.wait()
        print("command isawaitable: ", inspect.isawaitable(action))
        print("command action.data: ", action.data)
        print("command action.status: ", action.status)
        print("command action.results: ", action.results)
    except Exception as error:
        print(error)

and here are the results for Juju 2.9

(.venv) ubuntu@rgildein-bastion:~$ juju status
Model  Controller             Cloud/Region             Version  SLA          Timestamp
test   rgildein2-serverstack  serverstack/serverstack  2.9.35   unsupported  18:40:23Z

App      Version  Status  Scale  Charm    Channel  Rev  Exposed  Message
grafana           active      1  grafana  stable    69  no       Ready

Unit        Workload  Agent  Machine  Public address  Ports     Message
grafana/0*  active    idle   0        10.5.1.81       3000/tcp  Ready

Machine  State    Address    Inst id                               Series  AZ    Message
0        started  10.5.1.81  049ee5ba-4cff-4b41-bdca-1f18d676043f  focal   nova  ACTIVE

(.venv) ubuntu@rgildein-bastion:~$ pip freeze | grep juju
juju==2.9.46.1
jujubundlelib==0.5.7
(.venv) ubuntu@rgildein-bastion:~$ python3 ./zaza-test-script.py 
command isawaitable:  False
command action.data:  {'model-uuid': '5972fd83-b71d-4746-8dde-11b1ab1026f5', 'id': '24', 'receiver': 'grafana/0', 'name': 'juju-run', 'parameters': {'command': 'echo HelloWord', 'timeout': 0, 'workload-context': False}, 'status': 'completed', 'message': '', 'results': {'Code': '0', 'Stdout': 'HelloWord\n'}, 'enqueued': '2024-04-15T18:40:51Z', 'started': '2024-04-15T18:40:54Z', 'completed': '2024-04-15T18:40:54Z'}
command action.status:  completed
command action.results:  {'Code': '0', 'Stdout': 'HelloWord\n'}
command isawaitable:  False
command action.data:  {'model-uuid': '5972fd83-b71d-4746-8dde-11b1ab1026f5', 'id': '24', 'receiver': 'grafana/0', 'name': 'juju-run', 'parameters': {'command': 'echo HelloWord', 'timeout': 0, 'workload-context': False}, 'status': 'completed', 'message': '', 'results': {'Code': '0', 'Stdout': 'HelloWord\n'}, 'enqueued': '2024-04-15T18:40:51Z', 'started': '2024-04-15T18:40:54Z', 'completed': '2024-04-15T18:40:54Z'}
command action.status:  completed
command action.results:  {'Code': '0', 'Stdout': 'HelloWord\n'}
command isawaitable:  False
command action.data:  {'model-uuid': '5972fd83-b71d-4746-8dde-11b1ab1026f5', 'id': '26', 'receiver': 'grafana/0', 'name': 'juju-run', 'parameters': {'command': 'actions/get-admin-password', 'timeout': 0, 'workload-context': False}, 'status': 'completed', 'message': '', 'results': {'Code': '0', 'password': 'K5xgXHBM4jYwwtgt'}, 'enqueued': '2024-04-15T18:40:54Z', 'started': '2024-04-15T18:40:54Z', 'completed': '2024-04-15T18:40:55Z'}
command action.status:  completed
command action.results:  {'Code': '0', 'password': 'K5xgXHBM4jYwwtgt'}
command isawaitable:  False
command action.data:  {'model-uuid': '5972fd83-b71d-4746-8dde-11b1ab1026f5', 'id': '26', 'receiver': 'grafana/0', 'name': 'juju-run', 'parameters': {'command': 'actions/get-admin-password', 'timeout': 0, 'workload-context': False}, 'status': 'completed', 'message': '', 'results': {'Code': '0', 'password': 'K5xgXHBM4jYwwtgt'}, 'enqueued': '2024-04-15T18:40:54Z', 'started': '2024-04-15T18:40:54Z', 'completed': '2024-04-15T18:40:55Z'}
command action.status:  completed
command action.results:  {'Code': '0', 'password': 'K5xgXHBM4jYwwtgt'}

and results for Juju 3.4:

(.venv) ubuntu@juju-lxd-34:~$ juju status
Model  Controller  Cloud/Region         Version  SLA          Timestamp
test   lxd         localhost/localhost  3.4.2    unsupported  18:42:50Z

App      Version  Status  Scale  Charm    Channel        Rev  Exposed  Message
grafana           active      1  grafana  latest/stable   69  no       Ready

Unit        Workload  Agent  Machine  Public address  Ports     Message
grafana/0*  active    idle   0        10.205.200.72   3000/tcp  Ready

Machine  State    Address        Inst id        Base          AZ  Message
0        started  10.205.200.72  juju-1d3ff7-0  [email protected]      Running
(.venv) ubuntu@juju-lxd-34:~$ pip freeze | grep juju
juju==3.4.0.0
(.venv) ubuntu@juju-lxd-34:~$ python3 ./zaza-test-script.py 
command isawaitable:  False
command action.data:  {'model-uuid': 'a330379b-c75f-4a98-8726-10dfd71d3ff7', 'id': '30', 'receiver': 'grafana/0', 'name': 'juju-exec', 'status': 'pending', 'message': '', 'enqueued': '2024-04-15T18:43:15Z', 'started': '0001-01-01T00:00:00Z', 'completed': '0001-01-01T00:00:00Z'}
command action.status:  pending
command action.results:  {}
command isawaitable:  False
command action.data:  {'model-uuid': 'a330379b-c75f-4a98-8726-10dfd71d3ff7', 'id': '30', 'receiver': 'grafana/0', 'name': 'juju-exec', 'status': 'completed', 'message': '', 'enqueued': '2024-04-15T18:43:15Z', 'started': '2024-04-15T18:43:15Z', 'completed': '2024-04-15T18:43:15Z'}
command action.status:  completed
command action.results:  {'return-code': 0, 'stdout': 'HelloWord\n'}
command isawaitable:  False
command action.data:  {'model-uuid': 'a330379b-c75f-4a98-8726-10dfd71d3ff7', 'id': '32', 'receiver': 'grafana/0', 'name': 'juju-exec', 'status': 'pending', 'message': '', 'enqueued': '2024-04-15T18:43:16Z', 'started': '0001-01-01T00:00:00Z', 'completed': '0001-01-01T00:00:00Z'}
command action.status:  pending
command action.results:  {}
command isawaitable:  False
command action.data:  {'model-uuid': 'a330379b-c75f-4a98-8726-10dfd71d3ff7', 'id': '32', 'receiver': 'grafana/0', 'name': 'juju-exec', 'status': 'completed', 'message': '', 'enqueued': '2024-04-15T18:43:16Z', 'started': '2024-04-15T18:43:16Z', 'completed': '2024-04-15T18:43:17Z'}
command action.status:  completed
command action.results:  {'password': 'pxVVZpZGrcgCdqpH', 'return-code': 0}

The example of usage on both 2.9 and 3.4 (see logs) can be found here. The func tests are failing, but it's not related with zaza.
fixes: #649

@freyes
Copy link
Member

freyes commented Apr 16, 2024

I will run this change in one of the charms, with the CI. - https://review.opendev.org/c/openstack/charm-mysql-innodb-cluster/+/915994

@freyes
Copy link
Member

freyes commented Apr 16, 2024

@rgildein , can you take the chance of enabling juju 3.4 in the CI? - https://github.com/openstack-charmers/zaza/blob/master/.github/workflows/tox.yaml#L38 .

@rgildein
Copy link
Contributor Author

@rgildein , can you take the chance of enabling juju 3.4 in the CI? - https://github.com/openstack-charmers/zaza/blob/master/.github/workflows/tox.yaml#L38 .

Done

Add simply helper function with trying to pass parameter block=True
to unit.run and catch TypeError and run without parameter block.
@rgildein rgildein force-pushed the chore/no-ref/fix-action-object branch from a946a2d to faf2d52 Compare April 17, 2024 09:35
Copy link

codecov bot commented Apr 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 89.53%. Comparing base (b22c2ee) to head (8b06c8e).
Report is 2 commits behind head on master.

❗ Current head 8b06c8e differs from pull request most recent head 14bab3a. Consider uploading reports for the commit 14bab3a to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #655      +/-   ##
==========================================
- Coverage   89.54%   89.53%   -0.01%     
==========================================
  Files          45       45              
  Lines        4762     4759       -3     
==========================================
- Hits         4264     4261       -3     
  Misses        498      498              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@freyes freyes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the effort put into this. I'm just waiting for the CI results on this change - https://review.opendev.org/c/openstack/charm-mysql-innodb-cluster/+/915994 - to merge.

note: the ci failure in the 'third' test, it's not related to this change.



async def unit_run(unit, command, timeout=None):
"""Help function to help support Juju 2.9 and Juju 3>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could we change this docstring to be more descriptive? For example,

Helper function to support running `unit.run` for both Juju 2.9 and Juju 3.x versions.

@rgildein rgildein changed the title Switch to use action status to determin if wait Fix unit.run to support Juju 2.9 and 3.x Apr 18, 2024
@freyes
Copy link
Member

freyes commented Apr 18, 2024

LGTM. Thanks for the effort put into this. I'm just waiting for the CI results on this change - https://review.opendev.org/c/openstack/charm-mysql-innodb-cluster/+/915994 - to merge.

note: the ci failure in the 'third' test, it's not related to this change.

jammy https://openstack-ci-reports.ubuntu.com/artifacts/f20/915994/2/check/jammy/f2025fa/ : SUCCESS in 1h 18m 51s

the focal job failed, because an undercloud issue, so I won't block this PR on that.

@freyes freyes merged commit 6787575 into openstack-charmers:master Apr 18, 2024
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The behavior of model.run_on_unit has been changed to run only actions
3 participants