Plugin: wait-for

In the up and coming 2.9 release there will be a new Juju plugin; wait-for. The wait-for plugin is the start of a standardising step for waiting for a given entity to reach a goal state.

The wait-for command aims to address the one key concern that other predecessors struggle with; performance. The wait-for command uses the AllWatcher API instead of the Status API. Unfortunately there is a long running issue that means that requesting the full status from Juju creates a lot of queries to the database and can cause a dramatic slowdown. If you’re only concerned with one application or one unit, this seems very wasteful.

Instead the wait-for command uses the same principal as the model-cache and pylibjuju, by listening to the changes from the AllWatcher we can create a view of the world as it happens.


The wait-for command currently supports the following entities (others are being added):

  • Application
  • Machine
  • Model
  • Unit


As long as there is a bootstrapped controller, you can run the wait-for command before or after you apply the changes to Juju, either way doesn’t matter.

juju deploy mysql
juju wait-for application mysql --query='status=="active"'

Controller/other models

Targeting the controller or other models without switching can be done in the normal Juju standardised way via the -m flag.

juju wait-for -m controller machine 0 --query='status=="started" && life=="alive"'


Timeout values are represented as signed sequence of decimal numbers with a unit suffix i.e. 1h, 10m30s.

juju wait-for application mysql --query='status=="active"` --timeout=10m

Advanced queries

There are some more advanced queries that you can perform to ensure that your given entity meets its goal state.

Supported operators in the query are as follows:

  • && and || logical operators
  • == and != equality comparisions
  • >, >=, < and <= numeric comparisons (will work with strings as well)
Len function

len function is a builtin function that allows you to perform a length check on the following types:

  • maps
  • slices
  • strings
juju wait-for model -m controller controller --query='len(config) > 0 && config["agent-stream"] == "released"'
ForEach function

forEach function is a builtin function that allows the iteration of sub entities to ensure their goal state matches the query. The forEach will only work for maps of entity scope types:

  • Models
    • applications
    • machines
    • units

For example the following query waits for all applications to wait for the status to become active.

juju wait-for model default --query='forEach(applications, app => app.status == "active")'
Print function

print function is a builtin function that allows you to place a print function into a query to see the value. As everything is an expression then it also returns the same value.

juju wait-for model -m controller controller --query='len(print(config)) > 0 && config["agent-stream"] == "released"'

Hi !
Nice improvement, would be great to be able to use such thing in a bundle deployment because what I see now is that deploying with a bundle is very chaotic because many charms are deployed in parallel (which is great) but without any kind of ordering or priority.
One example : with a classical Openstack deployment, you will rely on mysql-innodb-cluster for all the Openstack control plane components such as keyston, nova, neutron, …
That means dozen of Charms that are waiting for their shared-db relation adding load to the system and IO pressure which, at the same time, can make mysql-innodb-cluster even longer to deploy.

Would be great to be able to have some kind of wait-for or require statement in the bundle to provide some ordering in the deployment process.

For example, would be great to have something like this :

    num_units: 1
    - lxd:0
      openstack-origin: *openstack-origin
      preferred-api-version: 3
      "": ost-int
      admin: ost-pub
      public: ost-pub 
    - mysql-innodb-cluster
    - vault

You get the idea I think.

Best regards

1 Like