X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=docs%2Fnarrative%2Fmodel.rst;h=036f43faa9a11572f66245acbb4b23d254b07d92;hb=fe19bc72a387b03fb157c873313ecac58b65e338;hp=c27179d0da27e7a09aa159e55f78b877849e5e99;hpb=843e6a04a7f92cc7efdcc75ae0bb4be3fb0ca027;p=osm%2FN2VC.git diff --git a/docs/narrative/model.rst b/docs/narrative/model.rst index c27179d..036f43f 100644 --- a/docs/narrative/model.rst +++ b/docs/narrative/model.rst @@ -4,6 +4,8 @@ A Juju controller provides websocket endpoints for each of its models. In order to do anything useful with a model, the juju lib must connect to one of these endpoints. There are several ways to do this. +For api docs, see :class:`juju.model.Model`. + Connecting to the Current Model ------------------------------- @@ -127,3 +129,98 @@ Example of creating a new model and then destroying it. See await model.disconnect() await controller.destroy_model(model.info.uuid) model = None + + +Reacting to Changes in a Model +------------------------------ +To watch for and respond to changes in a model, register an observer with the +model. The easiest way to do this is by creating a +:class:`juju.model.ModelObserver` subclass. + +.. code:: python + + from juju.model import Model, ModelObserver + + class MyModelObserver(ModelObserver): + async def on_change(self, delta, old, new, model): + # The raw change data (dict) from the websocket. + print(delta.data) + + # The entity type (str) affected by this change. + # One of ('action', 'application', 'annotation', 'machine', + # 'unit', 'relation') + print(delta.entity) + + # The type (str) of change. + # One of ('add', 'change', 'remove') + print(delta.type) + + # The 'old' and 'new' parameters are juju.model.ModelEntity + # instances which represent an entity in the model both before + # this change was applied (old) and after (new). + + # If an entity is being added to the model, the 'old' param + # will be None. + if delta.type == 'add': + assert(old is None) + + # If an entity is being removed from the model, the 'new' param + # will be None. + if delta.type == 'remove': + assert(new is None) + + # The 'old' and 'new' parameters, when not None, will be instances + # of a juju.model.ModelEntity subclass. The type of the subclass + # depends on the value of 'delta.entity', for example: + # + # delta.entity type + # ------------ ---- + # 'action' -> juju.action.Action + # 'application' -> juju.application.Application + # 'annotation' -> juju.annotation.Annotation + # 'machine' -> juju.machine.Machine + # 'unit' -> juju.unit.Unit + # 'relation' -> juju.relation.Relation + + # Finally, the 'model' parameter is a reference to the + # juju.model.Model instance to which this observer is attached. + print(id(model)) + + + model = Model() + await model.connect_current() + + model.add_observer(MyModelObserver()) + + +Every change in the model will result in a call to the `on_change()` +method of your observer(s). + +To target your code more precisely, define method names that correspond +to the entity and type of change that you wish to handle. + +.. code:: python + + from juju.model import Model, ModelObserver + + class MyModelObserver(ModelObserver): + async def on_application_change(self, delta, old, new, model): + # Both 'old' and 'new' params will be instances of + # juju.application.Application + pass + + async def on_unit_remove(self, delta, old, new, model): + # Since a unit is being removed, the 'new' param will always + # be None in this handler. The 'old' param will be an instance + # of juju.unit.Unit - the state of the unit before it was removed. + pass + + async def on_machine_add(self, delta, old, new, model): + # Since a machine is being added, the 'old' param will always be + # None in this handler. The 'new' param will be an instance of + # juju.machine.Machine. + pass + + async def on_change(self, delta, old, new, model): + # The catch-all handler - will be called whenever a more + # specific handler method is not defined.