Skip to content

Change Instances

A change instance represents a lifecycle event on a service item — a create, modify, or delete request. Automation pipelines watch for change instances, process them (provision/update/teardown infrastructure), and then update the state accordingly.

Accessed via client.change_instances.

Change types

change_type Description
CREATE A new service item is being provisioned for the first time
MODIFY An existing service item's configuration is changing
DELETE A service item is being decommissioned

States

state Description
PENDING Submitted but not yet acted on
APPROVED Approved and being processed
COMPLETED Successfully processed
ERROR Processing was attempted but failed
REJECTED Rejected as invalid before processing
CLOSED Closed without being processed (e.g. after an error or rejection)

Lifecycle: - PENDING → approved → APPROVED → success → COMPLETED - PENDING → rejected → REJECTEDCLOSED - APPROVED → failure → ERRORCLOSED

Model properties

Property Type Description
id int Change instance ID
state str Current state
change_type str CREATE, MODIFY, or DELETE
declaration dict Consumer's requested configuration — for CREATE change types. For MODIFY, use ci.data['new_declaration'] and ci.data['old_declaration'] instead.
service_item_id int Associated service item ID
service_id int Associated service ID
deployed_item_id int Associated deployed item ID (set once fulfilled)
created datetime Creation timestamp
modified datetime Last modified timestamp

Methods

list(**filters)

Returns a lazy generator of change instances. Use this for large result sets where you want to process items one at a time without loading everything into memory.

Filters:

Filter Type Description
state str Filter by state (PENDING, APPROVED, COMPLETED, ERROR, REJECTED, CLOSED)
change_type str Filter by change type (CREATE, MODIFY, DELETE)
service_id int Filter by service ID
service_item_id int Filter by service item ID
application_id int Filter by application ID
consumer_team_id int Filter by consumer team ID
service_name str Filter by service name
service_owner_team_id int Filter by service owner team ID
submission_id int Filter by the submission that created the change instance
commit_id str Filter by commit ID
start_date str Filter by creation date (ISO format, inclusive lower bound)
end_date str Filter by creation date (ISO format, inclusive upper bound)
modified str Filter by last modified date
exclude_referenced bool Exclude change instances that are referenced by others
ordering str Sort field — prefix with - for descending (e.g. created, -modified)
# All change instances
for ci in client.change_instances.list():
    print(ci.id, ci.state, ci.change_type)

# All pending change instances
for ci in client.change_instances.list(state="PENDING"):
    print(ci.id, ci.change_type)

# All pending CREATEs for a specific service
for ci in client.change_instances.list(service_id=45, state="PENDING", change_type="CREATE"):
    print(ci.id, ci.declaration)

filter(**filters)

Same as list() but returns all results as a list. Accepts the same filters.

# All pending DELETEs for a service
deletes = client.change_instances.filter(
    service_id=45,
    state="PENDING",
    change_type="DELETE"
)
print(f"{len(deletes)} pending deletions")

# Most recent first
recent = client.change_instances.filter(ordering="-created")

# All errors across all services
errors = client.change_instances.filter(state="ERROR")

get(id)

Retrieves a single change instance by ID. Raises NetorcaNotFoundError if not found.

ci = client.change_instances.get(456)

print(ci.id)
print(ci.state)
print(ci.change_type)
print(ci.service_item_id)
print(ci.service_id)
print(ci.deployed_item_id)  # set once a deployed item is created
print(ci.created)
print(ci.modified)

# For CREATE change types
print(ci.declaration)           # the consumer's full declaration

# For MODIFY change types, access new_declaration / old_declaration via raw data
print(ci.data['new_declaration'])   # what the consumer wants it to be
print(ci.data['old_declaration'])   # what it was before

update(id, data, partial=True)

Updates a change instance — most commonly used to advance its state. Defaults to PATCH.

Parameter Type Description
id int Change instance ID
data dict Fields to update
partial bool True (default) = PATCH, False = PUT
# Approve a pending change instance
client.change_instances.update(456, {"state": "APPROVED"})

# Mark as completed after provisioning
client.change_instances.update(456, {"state": "COMPLETED"})

# Mark as errored with a log message
client.change_instances.update(456, {
    "state": "ERROR",
    "log": "Provisioning failed: disk quota exceeded"
})

# Close without processing
client.change_instances.update(456, {"state": "CLOSED"})

get_history(change_instance_id)

Returns the full audit history of a change instance — every state transition, update, and action taken on it, in order.

Parameter Type Description
change_instance_id int Change instance ID
history = client.change_instances.get_history(change_instance_id=456)
for entry in history:
    print(entry)

get_dependant()

Returns change instances that depend on this change instance — i.e. change instances that cannot proceed until this one is resolved. Returns a list of raw dicts.

dependants = client.change_instances.get_dependant()
for dep in dependants:
    print(dep)

get_referenced(**filters)

Returns change instances that are referenced by other change instances. Useful for tracing relationships across a complex provisioning graph.

Filters: same as list().

referenced = client.change_instances.get_referenced(state="PENDING")
for ci in referenced:
    print(ci)

Typical automation pattern

A service owner automation loop watches for pending change instances, processes them, and updates the state:

# Provision new service items
for ci in client.change_instances.filter(service_id=45, state="PENDING", change_type="CREATE"):
    try:
        desired_config = ci.declaration   # what the consumer requested
        # ... provision the resource ...
        client.change_instances.update(ci.id, {"state": "COMPLETED"})
    except Exception as e:
        client.change_instances.update(ci.id, {"state": "ERROR", "log": str(e)})

# Apply modifications
for ci in client.change_instances.filter(service_id=45, state="PENDING", change_type="MODIFY"):
    new_config = ci.data['new_declaration']   # what consumer wants it to be
    old_config = ci.data['old_declaration']   # what it currently is
    # ... apply the change ...
    client.change_instances.update(ci.id, {"state": "COMPLETED"})

# Tear down decommissioned items
for ci in client.change_instances.filter(service_id=45, state="PENDING", change_type="DELETE"):
    print(f"Removing service item {ci.service_item_id}")
    # ... tear down the resource ...
    client.change_instances.update(ci.id, {"state": "COMPLETED"})