Change Syntax

Here is the definitive guide for how to define a change to do whatever it is you want it to do.

Change Block

The most basic change definition looks like this:

<change name='mychange' type='CommandChange'>
</change>

Every change must have a name and a type. The name is used when referring to the change from elsewhere in the configuration, such as when defining dependencies. The type is used to define what kind of change this is, and thus how it will communicate with device when running through its stages.

The type of the change affects what options are supported in its configuration. There are a few core settings that are always available, but some setting are only supported by certain change types, and not others.

The example change is a CommandChange. CommandChanges use an expect/send style communications method which we will discuss later. We will also discuss a ZAPIChange, and show how the configuration settings available are different to those of a CommandChange.

The choice of change type affects which Provisioners are supported for effecting the change on remote devices. A CommandChange will be run by a Provisioner that supports the CommandChange interface.

Change Targets

In order to modify something on a remote device, you will need to give it a target.

<change name='mychange' type='CommandChange'>
  <target name='device_name'/>
</change>

The name attribute of the target defines which previously defined Device the target will be applied to.

The change will be applied to each target exactly once. ModiPy keeps track of which devices have had the change applied to it so that if a change fails partway through, and it is backed out, ModiPy will back out the change on every device that the change was successfully applied to.

You can also define a special target called ALL_TARGETS, which will make the change apply to all the devices defined in the system, including any defined dynamically via the commandline. You use it like this:

<change name='mychange' type='CommandChange'>
  <target name='ALL_TARGETS'/>
</change>

Change Dependencies

There are 2 ways to define dependencies between changes:

  • Within the changes themselves
  • Outside the changes, linking them together

Dependencies defined within changes

Defining the dependencies for a change is quite simple. All you need to know is the names of the changes that have to complete before this change is able to run, and you add them to the change definition like this:

<change name='mychange' type='CommandChange'>
  <depends on='change_name_1'/>
  <depends on='change_name_2'/>
</change>

This change will now not be attempted until both change_name_1 and change_name_2 have both completed successfully.

Dependencies defined outside changes

For more advanced changesets, it may be necessary to define change dependencies separately from the changes themselves. ModiPy also provides a mechanism for doing this.

You define a new configuration block, outside of any changes, like this:

<config>
...
<dependencies>
  <before changename='change_blue'>
    <require changename='change_yellow'/>
    <require changename='change_red'/>
  </before>
  <before changename='change_green'>
    <require changename='change_blue'/>
  </before>
</dependencies>

</config>

This set of configuration tells ModiPy that change change_yellow and change_red must complete before change_blue will be tried, and that change_green depends on change_blue to complete before it will be tried.

Some people may find this method of defining change dependencies more natural for even simple cases, such as this one.

For more complex changesets that involve dynamic elements, it may not be possible to define change dependencies internally within changes. You would then need to use this second method for defining change dependencies.

Iterators

Another useful change attribute is an iterator. You use one like this:

<change name='mychange' type=CommandChange' iterator='my_named_iterator'>

An iterator makes a change run more than once. In fact, it will run once for each item in the iterator, on every device that the change has as a target.