Skip to content

Entity Acquisition (Acquire)

In plain terms, acquire answers the question: "What data does this workflow (or step) need before it can run?" Think of it as a shopping list -- you declare what entities you need, and the engine fetches and locks them for you before execution begins.

The acquire clause lets workflows pull additional entities into the execution context beyond the initial seed entities. This is how you expand the data available to your steps -- for example, loading all interfaces for a device, or selecting specific devices by Elasticsearch query.

Where to Use Acquire

Acquire can be defined at two levels:

  • Root level -- Acquires entities for the entire workflow, before any steps execute
  • Step level -- Acquires entities for a specific step, just before that step executes

Acquire Types

Elastic Query

Select entities using Elasticsearch query syntax against the CMS:

acquire:
  - type: elastic
    entity: device
    query: "facts.netbox_id: *"
    assertNotEmpty: true
    description: "Select devices that have a NetBox ID"

This acquires devices whose facts.netbox_id field has a value. The engine queries the CMS's Elasticsearch index and adds matching devices to the context.

Field Required Description
type Yes elastic
entity Yes Entity type to query (device, interface, group)
query Yes Elasticsearch query string
assertNotEmpty No Fail if the query returns no results
limit No Max entities to return
description No Human-readable explanation

Expansion

Expand the context from the seed entity. Commonly used to load interfaces for devices:

acquire:
  - type: expansion
    entity: interface
    expandFromSeedEntity: true
    description: "Load all interfaces for each device"
Field Required Description
type Yes expansion
entity Yes Entity type to expand to (interface, device, group)
expandFromSeedEntity Yes Whether to expand from the seed entity
assertNotEmpty No Fail if expansion returns no entities
description No Human-readable explanation

Context

Reference entities already in the context, optionally filtering them:

acquire:
  - type: context
    entity: interface
    filter: "state == 'UP'"
Field Required Description
type Yes context
entity Yes Entity type to filter
filter No JMESPath filter expression

Reference

Reference entities acquired by a previous step:

acquire:
  - type: reference
    entity: device
    label: discovery_step

This adds the devices that were referenced in the step labeled discovery_step to the current context.

Field Required Description
type Yes reference
entity Yes Entity type
label Yes Label of the step to reference

Practical Example

A network health check that first acquires devices by query, then expands to include their interfaces:

acquire:
  - type: elastic
    entity: device
    query: "platform.shortName: ios AND connection_state: OK"
    assertNotEmpty: true
    description: "Select all reachable Cisco IOS devices"
  - type: expansion
    entity: interface
    expandFromSeedEntity: true
    description: "Include all interfaces for each device"

Execution Flow

  1. Root acquire runs during the RESOURCE_DISCOVERY phase, before any steps execute
  2. For declarative acquire types (elastic, expansion, context, reference), the engine resolves them directly via the CMS -- no worker involvement
  3. For function-block-level acquire (defined by the FB's acquire() method), the engine creates ACQUIRE jobs on the blackboard, which workers execute
  4. The engine fetches and locks the requested entities from the CMS
  5. Step acquire runs just before the step, expanding the context available to that step
Why acquire is a separate phase

The acquire phase exists to decouple entity selection from execution. This enables the engine to lock all required entities before any step runs, preventing concurrent workflows from creating conflicts. It also allows function blocks to dynamically determine what data they need at runtime, rather than requiring everything to be specified statically in the workflow definition.


See also: