Components

Modules

Modules are the primary data-type in Runcible. They are used to represent both the user’s desired state for a given device as well as tracking the current state of a device. They can be generated from JSON, YAML, or a Python Dict (if you are using the API.)

In general, Modules have a very simple structure, they have a name and attributes:

module_name:
    attribute1: value1
    attribute2: value2

An example of the ntp_client module as implemented by the Cumulus driver:

ntp_client:
    interface: eth0
    servers:
    - 0.cumulusnetworks.pool.ntp.org
    - 1.cumulusnetworks.pool.ntp.org
    - 2.cumulusnetworks.pool.ntp.org
    - 3.cumulusnetworks.pool.ntp.org

There are also some special modules that behave differently.

Special Modules

Module Array

Module Arrays are a wrapper that allows a number of modules to exist under a parent module. For example:

parent_module:
    - key: sub_module_1
      attribute: value
    - key: sub_module_2
      attribute: value

The most common use case for Module Arrays are interfaces, bonds, and vlans, for example here is an example of the bonds module array as implemented by the Cumulus driver:

bonds:
- name: po1
  pvid: 1
  slaves:
  - swp1
  - swp2
- name: po2
  pvid: 1
  slaves:
  - swp3
  - swp4

Meta Modules

TBD

Schedulers

Schedulers determine the run-order of Runcible’s execution stage (when changes are actually made). They govern many aspects of the “bigger picture” when configuring multiple devices, such as:

  • The order in which the devices are configured

  • Ensuring that certian groups of devices aren’t configured at the same time

  • Controlling failure behavior (I.E. failure of a core device results in a stop/rollback of the execution process)

  • Rollback and failure behavior

Needs

What is a need?

A need is a datatype that abstracts state changes. Needs can be simplified into a formatted string:

<parent_module>.<module>.<attribute>.<command> <value> Where both the parent module and value are optional. For example:

vlans.12.ipv4_addr.SET: 10.1.2.3/24 Is a need that represents setting the ipv4_addr of the vlan sub_module for vlan 12 to 10.1.2.3.

ntp_client.servers.DEL: 0.pool.ntp.org Is a need that represents removing the value 0.pool.ntp.org from the list of ntp servers.

Needs are tightly couple to module attribute pathing, so the attribute:

system:
  hostname: test

Would be modified by a need of system.hostname.SET: newhostname.

How do they get generated?

Needs are generated by Runcible automatically when you provide a desired state and call the command apply. For instance:

[mergedb_getting_started]$ runcible ".*" apply -m .
The following changes will be applied:
Device core:
==========================================
vlans needs:
    vlans.10.CREATE
    vlans.20.CREATE
    vlans.30.CREATE
interfaces needs:
    interfaces.swp1.vlans.ADD: 10
    interfaces.swp1.vlans.ADD: 20
    interfaces.swp1.vlans.ADD: 30
    interfaces.swp2.vlans.ADD: 10
    interfaces.swp2.vlans.ADD: 20
    interfaces.swp2.vlans.ADD: 30
    interfaces.swp3.vlans.ADD: 10
    interfaces.swp3.vlans.ADD: 20
    interfaces.swp3.vlans.ADD: 30

What occured is that Runcible examined the current state and desired state, and generated a list of needs that are required to bring the two into alignment. Needs provide idempotency in a way that doesn’t require Plugin developers to worry about state, as Runcible abstracts the state into Needs.

Needs and ad-hoc commands

You can also apply needs from the command line. By specifying a need string in lieu of special_functions, you can easily make changes without having to create a desired state data source.

For instance:

$ runcible -m /home/grayson/PycharmProjects/runcible/examples/cumulus_mclag 'spine1a' ntp_client.interface.GET
Device spine1a:
==========================================
eth0

Need Operations

Need objects support the following operations:

SET

Boolean: set sets the boolean to either True or False List: set replaces the entire list with a new list String: replaces the string with the new string Integer: replaces the integer with the new integer

DELETE

List: must be specified with a value, and only deletes the value specified String: removes the string Integer: removes the integer

CLEAR

List: deletes the whole list

GET

Only used by ad-hoc commands, returns the value of the attribute

ADD

List: adds a new value (or values) to the list

CREATE

Module: Creates a sub-module within a module array

REMOVE

Module: Deletes a sub-module within a module array