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 → REJECTED → CLOSED
- APPROVED → failure → ERROR → CLOSED
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.
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"})