Adding a Core Adapter
Relevant source files
The following files were used as context for generating this wiki page:
An adapter serves as the connector between infrahub-sync and external systems of record. It enables the project to read data from a source or write data to a destination by implementing a specific contract based on the diffsync framework. Adapters must provide a read-only path via list and diff commands before enabling the mutating sync pathway.
Sources: dev/knowledge/sync-architecture.md:5-10, dev/constitution.md:16-20
Adapter Architecture
The adapter system consists of two primary classes defined in a single module under infrahub_sync/adapters/<name>.py. The Adapter Class manages the connection and object loading, while the Model Class provides the template for generated DiffSync models.
Class Hierarchy
When writing an adapter, you must inherit from the project-specific mixins before the diffsync base classes. This ensures that infrahub-sync methods take precedence.
The diagram shows the required inheritance pattern where mixins are declared first to satisfy the adapter contract.
Sources: dev/knowledge/adapter-anatomy.md:9-30, dev/guidelines/writing-an-adapter.md:10-18
Implementation Workflow
Adding an adapter follows a standard sequence from environment setup to documentation.
- Choose a Base: Subclass
GenericrestapiAdapterfor REST APIs or use a freshDiffSyncMixinfor bespoke SDKs. - Initialize Client: Create an upstream client in
__init__, reading credentials from environment variables first, then falling back tosettings. - Implement model_loader: This method must fetch records, apply filters/transforms via the model mixin, and add them to the store.
- Define Write Methods: If the system is a destination, implement
create,update, anddeletein the model class. - Create Schema Mapping: Write a
config.ymlthat maps source fields to destination models.
Sources: dev/guides/adding-an-adapter.md:32-75, dev/guidelines/writing-an-adapter.md:56-65
Data Flow during Load
The following sequence describes how data moves from a remote system into the in-memory store.
This flow illustrates the requirement to use mixin methods for filtering and transforming to ensure consistent behavior across all adapters.
Sources: dev/knowledge/adapter-anatomy.md:35-45, dev/guidelines/writing-an-adapter.md:25-30
Core Methods and Tiers
Adapters implement a specific set of methods to participate in the sync lifecycle.
| Method | Role | Requirement |
|---|---|---|
model_loader | Fetches and prepares data for the DiffSync store. | Must implement |
cursor_tier_for | Declares the incremental sync strategy (NONE, ID, or TIMESTAMP). | Optional (defaults to NONE) |
list_changed_since | Yields records modified since a specific cursor. | Required if tier > NONE |
list_existing_ids | Yields all current unique IDs to detect deletions. | Optional |
Sources: dev/knowledge/adapter-anatomy.md:46-55, dev/knowledge/incremental-and-cache.md:9-25
Development Standards
Logging and Security
- Use
structlogfor all logging. - Never log tokens, passwords, or full authentication headers.
- Credentials must be handled via environment variables.
- Treat the upstream SDK as an optional dependency using
# ty: ignore[unresolved-import].
Sources: dev/guidelines/writing-an-adapter.md:46-65, dev/constitution.md:65-72
Verification
Validate the adapter using non-mutating CLI commands before attempting a sync:
infrahub-sync list: Verify the project is recognized.infrahub-sync generate: Ensure models are rendered correctly from the schema mapping.infrahub-sync diff: Calculate differences without writing to the destination.
Sources: dev/guides/adding-an-adapter.md:100-112, dev/constitution.md:23-28
Testing Requirements
Every adapter must ship with a unit test suite under tests/adapters/.
- Offline by Default: Tests must mock the upstream client using
unittest.mock. No network access is allowed in the default suite. - Coverage: Tests must verify field mapping,
local_idassignment, reference resolution, filters, and transforms. - Optional Dependencies: Use
pytest.importorskip("sdk_name")at the module top to avoid errors when an optional SDK is not installed.
Sources: dev/guides/testing-an-adapter.md:8-58, dev/guidelines/testing-adapters.md:9-16
Summary
Adding a core adapter requires implementing the DiffSyncMixin and DiffSyncModelMixin contracts, ensuring strict adherence to the project's security and logging standards. By following the read-only-first principle, developers can safely verify data transformations and mappings before enabling write operations on live infrastructure systems.