Inheritance
We have seen in the runtime tutorial how tasks can be grouped into families.
In this tutorial we will look at nested families, inheritance order and multiple inheritance.
Inheritance Hierarchy
Within your ~/cylc-src
directory create a new directory called
inheritance-tutorial
:
mkdir ~/cylc-src/inheritance-tutorial
cd ~/cylc-src/inheritance-tutorial
And paste the following code into a flow.cylc
file. This
defines two tasks each representing different aircraft, the Airbus A380 jumbo
jet and the Robson R44 helicopter:
[scheduling]
[[graph]]
R1 = a380 & r44
[runtime]
[[VEHICLE]]
init-script = echo 'Boarding'
pre-script = echo 'Departing'
post-script = echo 'Arriving'
[[AIR_VEHICLE]]
inherit = VEHICLE
[[[meta]]]
description = A vehicle which can fly.
[[AIRPLANE]]
inherit = AIR_VEHICLE
[[[meta]]]
description = An air vehicle with fixed wings.
[[[environment]]]
CAN_TAKE_OFF_VERTICALLY = false
[[HELICOPTER]]
inherit = AIR_VEHICLE
[[[meta]]]
description = An air vehicle with rotors.
[[[environment]]]
CAN_TAKE_OFF_VERTICALLY = true
[[a380]]
inherit = AIRPLANE
[[[meta]]]
title = Airbus A380 Jumbo-Jet.
[[r44]]
inherit = HELICOPTER
[[[meta]]]
title = Robson R44 Helicopter.
Note
The [meta]
section is a freeform section where we can define metadata
to be associated with a task, family or the workflow itself.
This metadata should not be mistaken for Rose Configuration Metadata.
Reminder
By convention we write family names in upper case (with the exception of the
special root
family) and task names in lower case.
These two tasks sit at the bottom of an inheritance tree. The cylc graph
command has an option (-n
) for drawing such inheritance hierarchies:
cylc graph -n . &
Running this command will generate the following output:
Note
The root
family sits at the top of the inheritance tree as all
tasks/families automatically inherit it:
Cylc handles inheritance by starting with the root family and working down the inheritance tree applying each section in turn.
To see the resulting configuration for the a380
task use the
cylc config
command:
cylc config . -i "[runtime][a380]"
You should see some settings which have been inherited from the VEHICLE
and
AIRPLANE
families as well as a couple defined in the a380
task.
init-script = echo 'Boarding' # Inherited from VEHICLE
pre-script = echo 'Departing' # Inherited from VEHICLE
post-script = echo 'Arriving' # Inherited from VEHICLE
inherit = AIRPLANE # Defined in a380
[[[meta]]]
description = An air vehicle with fixed wings. # Inherited from AIR_VEHICLE - overwritten by AIRPLANE
title = Airbus A380 Jumbo-Jet. # Defined in a380
[[[environment]]]
CAN_TAKE_OFF_VERTICALLY = false # Inherited from AIRPLANE
Note that the description
setting is defined in the AIR_VEHICLE
family but is overwritten by the value specified in the AIRPLANE
family.
Multiple Inheritance
Next we want to add a vehicle called the V-22 Osprey to the workflow. The V-22 is a cross between a plane and a helicopter - it has wings but can take-off and land vertically.
As the V-22 can be thought of as both a plane and a helicopter we want it to
inherit from both the AIRPLANE
and HELICOPTER
families. In Cylc we can
inherit from multiple families by separating their names with commas:
Add the following task to your flow.cylc
file.
[[v22]]
inherit = AIRPLANE, HELICOPTER
[[[meta]]]
title = V-22 Osprey Military Aircraft.
Re-run the cylc graph
command.
The inheritance hierarchy should now look like this:
Inspect the configuration of the v22
task using the cylc config
command.
Hint
cylc config . -i "[runtime][v22]"
You should see that the CAN_TASK_OFF_VERTICALLY
environment variable has
been set to false
which isn’t right. This is because of the order in which
inheritance is applied.
Cylc handles multiple-inheritance by applying each family from right to left.
For the v22
task we specified inherit = AIRPLANE, HELICOPTER
so the
HELICOPTER
family will be applied first and the AIRPLANE
family after.
The inheritance order would be as follows:
root
VEHICLE
AIR_VEHICLE
HELICOPTER # sets "CAN_TAKE_OFF_VERTICALLY to "true"
AIRPLANE # sets "CAN_TAKE_OFF_VERTICALLY to "false"
v22
We could fix this problem by changing the order of inheritance:
inherit = HELICOPTER, AIRPLANE
Now the HELICOPTER
family is applied second so its values will override any
in the AIRPLANE
family.
root
VEHICLE
AIR_VEHICLE
AIRPLANE # sets "CAN_TAKE_OFF_VERTICALLY to "false"
HELICOPTER # sets "CAN_TAKE_OFF_VERTICALLY to "true"
v22
Inspect the configuration of the v22
task using cylc config
to
confirm this.
More Inheritance
We will now add some more families and tasks to the workflow.
Engine Type
Next we will define four families to represent three different types of engine.
Each engine type should set an environment variable called FUEL
which we
will assign to the following values:
Turbine - kerosene
Internal Combustion - petrol
Human - pizza
Add lines to the runtime
section to represent these four families.
Solution
[[ENGINE]]
[[TURBINE_ENGINE]]
inherit = ENGINE
[[[environment]]]
FUEL = kerosene
[[INTERNAL_COMBUSTION_ENGINE]]
inherit = ENGINE
[[[environment]]]
FUEL = petrol
[[HUMAN_ENGINE]]
inherit = ENGINE
[[[environment]]]
FUEL = pizza
We now need to make the three aircraft inherit from one of the three engines. The aircraft use the following types of engine:
A380 - turbine
R44 - internal combustion
V22 - turbine
Modify the three tasks so that they inherit from the relevant engine families.
Solution
[[a380]]
inherit = AIRPLANE, TURBINE_ENGINE
[[[meta]]]
title = Airbus A380 Jumbo-Jet.
[[r44]]
inherit = HELICOPTER, INTERNAL_COMBUSTION_ENGINE
[[[meta]]]
title = Robson R44 Helicopter.
[[v22]]
inherit = AIRPLANE, HELICOPTER, TURBINE_ENGINE
[[[meta]]]
title = V-22 Ofsprey Military Aircraft.
Penny Farthing
Next we want to add a new type of vehicle, an old-fashioned bicycle called a penny farthing.
To do this we will need to add two new families, LAND_VEHICLE
and
BICYCLE
as well as a new task, penny_farthing
related in the
following manner:
Add lines to the runtime
section to represent the two new families and one
task outlined above.
Add a description ([meta]description
) to the LAND_VEHICLE
and
BICYCLE
families and a title ([meta]title
) to the penny_farthing
task.
Solution
[[LAND_VEHICLE]]
inherit = VEHICLE
[[[meta]]]
description = A vehicle which can travel over the ground.
[[BICYCLE]]
inherit = LAND_VEHICLE
[[[meta]]]
description = A small two-wheeled vehicle.
[[penny_farthing]]
inherit = BICYCLE, HUMAN_ENGINE
[[[meta]]]
title = An old-fashioned bicycle.
Using cylc config
to inspect the configuration of the penny_farthing
task we can see that it inherits settings from the VEHICLE
,
BICYCLE
and HUMAN_ENGINE
families.
inherit = BICYCLE, HUMAN_ENGINE
init-script = echo 'Boarding' # Inherited from VEHICLE
pre-script = echo 'Departing' # Inherited from VEHICLE
post-script = echo 'Arriving' # Inherited from VEHICLE
[[[environment]]]
FUEL = pizza # Inherited from HUMAN_ENGINE
[[[meta]]]
description = A small two-wheeled vehicle. # Inherited from LAND_VEHICLE - overwritten by BICYCLE
title = An old-fashioned bicycle. # Defined in penny_farthing
Hint
cylc config . -i "[runtime]penny_farthing"
Hovercraft
We will now add a hovercraft called the Hoverwork BHT130, better known to some as the Isle Of Wight Ferry.
Hovercraft can move over both land and water and in some respects can be thought of as flying vehicles.
Write new families and one new task to represent the above structure.
Add a description ([meta]description
) to the WATER_VEHICLE
and
HOVERCRAFT
families and a title ([meta]title
) to the bht130
task.
Solution
[[WATER_VEHICLE]]
inherit = VEHICLE
[[[meta]]]
description = A vehicle which can travel over water.
[[HOVERCRAFT]]
inherit = LAND_VEHICLE, AIR_VEHICLE, WATER_VEHICLE
[[[meta]]]
description = A vehicle which can travel over ground, water and ice.
[[bht130]]
inherit = HOVERCRAFT, INTERNAL_COMBUSTION_ENGINE
[[[meta]]]
title = Griffon Hoverwork BHT130 (Isle Of Whight Ferry).
Finished Workflow
You should now have a workflow with an inheritance hierarchy which looks like this: