octodns.provider.base

Classes

BaseProvider(id[, apply_disabled, ...])

Base class for all octoDNS providers.

class octodns.provider.base.BaseProvider(id, apply_disabled=False, update_pcent_threshold=0.3, delete_pcent_threshold=0.3, strict_supports=True, root_ns_warnings=True)[source]

Bases: BaseSource

Base class for all octoDNS providers.

Providers extend octodns.source.base.BaseSource to add the ability to apply DNS changes to a target system. While sources only need to implement populate() to read DNS data, providers also implement plan() and apply() to manage the complete sync workflow.

The provider workflow:

  1. Populate: Load current state from the provider via populate()

  2. Process: Modify zones through _process_desired_zone() and _process_existing_zone() to handle provider-specific limitations

  3. Plan: Compute changes between desired and existing state via plan()

  4. Apply: Submit approved changes to the provider via apply()

Subclasses must implement:

  • _apply(plan): Actually submit changes to the provider’s API/backend

Subclasses should override as needed:

  • _process_desired_zone(desired): Modify desired state before planning

  • _process_existing_zone(existing, desired): Modify existing state before planning

  • _include_change(change): Filter out false positive changes

  • _extra_changes(existing, desired, changes): Add provider-specific changes

  • _plan_meta(existing, desired, changes): Add metadata to the plan

Example provider configuration:

providers:
  route53:
    class: octodns_route53.Route53Provider
    access_key_id: env/AWS_ACCESS_KEY_ID
    secret_access_key: env/AWS_SECRET_ACCESS_KEY

Environment variables support default values that are used when the variable is not set:

providers:
  example:
    class: whatever.ExampleProvider
    region: env/AWS_REGION/us-east-1

zones:
  example.com.:
    sources:
      - config
    targets:
      - route53
__init__(id, apply_disabled=False, update_pcent_threshold=0.3, delete_pcent_threshold=0.3, strict_supports=True, root_ns_warnings=True)[source]

Initialize the provider.

Parameters:
  • id (str) – Unique identifier for this provider instance.

  • apply_disabled (bool) – If True, the provider will plan changes but not apply them. Useful for read-only/validation mode.

  • update_pcent_threshold (float) – Maximum percentage of existing records that can be updated in one sync before requiring --force. Default: 0.3 (30%).

  • delete_pcent_threshold (float) – Maximum percentage of existing records that can be deleted in one sync before requiring --force. Default: 0.3 (30%).

  • strict_supports (bool) – If True, raise exceptions when unsupported features are encountered. If False, log warnings and attempt to work around limitations.

  • root_ns_warnings (bool) – If True, log warnings about root NS record handling. If False, silently handle root NS.

_process_desired_zone(desired)[source]

Process the desired zone before planning.

Called during the planning phase to modify the desired zone records before changes are computed. This is where providers handle their limitations by removing or modifying records that aren’t supported. The parent method will deal with “standard” unsupported cases like types, dynamic, and root NS handling. The desired zone is a shallow copy (see octodns.zone.Zone.copy()).

Parameters:

desired (octodns.zone.Zone) – The desired zone state to be processed. This is a shallow copy that can be modified.

Returns:

The processed desired zone, typically the same object passed in.

Return type:

octodns.zone.Zone

Important

  • Must call super() at an appropriate point, generally as the final step of the method, returning the result of the super call.

  • May modify desired directly.

  • Must not modify records directly; record.copy() should be called, the results of which can be modified, and then Zone.add_record() may be used with replace=True.

  • May call Zone.remove_record() to remove records from desired.

  • Must call supports_warn_or_except() with information about any changes that are made to have them logged or throw errors depending on the provider configuration.

_process_existing_zone(existing, desired, lenient=False)[source]

Process the existing zone before planning.

Called during the planning phase to modify the existing zone records before changes are computed. This allows providers to normalize or filter the current state from the provider. The existing zone is a shallow copy (see octodns.zone.Zone.copy()).

Parameters:
  • existing (octodns.zone.Zone) – The existing zone state from the provider. This is a shallow copy that can be modified.

  • desired (octodns.zone.Zone) – The desired zone state. This is for reference only and must not be modified.

  • lenient (bool) – When True, relaxed validation rules should be applied when modifying zone records (e.g. passed to Zone.add_record()).

Returns:

The processed existing zone, typically the same object passed in.

Return type:

octodns.zone.Zone

Important

  • desired must not be modified in any way; it is only for reference.

  • Must call super() at an appropriate point, generally as the final step of the method, returning the result of the super call.

  • May modify existing directly.

  • Must not modify records directly; record.copy() should be called, the results of which can be modified, and then Zone.add_record() may be used with replace=True and lenient=lenient.

  • May call Zone.remove_record() to remove records from existing.

  • Must call supports_warn_or_except() with information about any changes that are made to have them logged or throw errors depending on the provider configuration.

_include_change(change)[source]

Filter out false positive changes.

Called during planning to allow providers to filter out changes that are false positives due to peculiarities in their implementation (e.g., providers that enforce minimum TTLs).

Parameters:

change (octodns.record.change.Change) – A change being considered for inclusion in the plan.

Returns:

True if the change should be included in the plan, False to filter it out.

Return type:

bool

_extra_changes(existing, desired, changes)[source]

Add provider-specific extra changes to the plan.

Called during planning to allow providers to add extra changes that are necessary to update ancillary record data or configure the zone (e.g., base NS records that must be managed separately).

Parameters:
  • existing (octodns.zone.Zone) – The existing zone state.

  • desired (octodns.zone.Zone) – The desired zone state.

  • changes (list[octodns.record.change.Change]) – The list of changes already computed.

Returns:

A list of additional changes to add to the plan. Return an empty list if no extra changes are needed.

Return type:

list[octodns.record.change.Change]

_plan_meta(existing, desired, changes)[source]

Indicate provider-specific metadata changes to the zone.

Called during planning to allow providers to indicate they have “meta” changes to the zone which are unrelated to records. Examples may include service plan changes, replication settings, and notes.

Parameters:
  • existing (octodns.zone.Zone) – The existing zone state.

  • desired (octodns.zone.Zone) – The desired zone state.

  • changes (list[octodns.record.change.Change]) – The list of changes computed for this plan.

Returns:

Arbitrary metadata about zone-level changes. The only requirement is that pprint.pformat can display it. A dict is recommended. Return None if no meta changes.

Return type:

dict or None

supports_warn_or_except(msg, fallback)[source]

Handle unsupported features based on strict_supports setting.

If strict_supports is True, raises a SupportsException. Otherwise, logs a warning with the message and fallback behavior.

Parameters:
  • msg (str) – Description of the unsupported feature or limitation.

  • fallback (str) – Description of the fallback behavior being used.

Raises:

SupportsException – If strict_supports is True.

plan(desired, processors=[], lenient=False)[source]

Compute a plan of changes needed to sync the desired state to this provider.

This is the main planning method that orchestrates the entire planning workflow. It populates the current state, processes both desired and existing zones, runs processors, computes changes, and returns a Plan object.

The planning workflow:

  1. Populate existing state from the provider via populate()

  2. Process desired zone via _process_desired_zone()

  3. Process existing zone via _process_existing_zone()

  4. Run target zone processors

  5. Run source and target zone processors

  6. Compute changes between existing and desired

  7. Filter changes via _include_change()

  8. Add extra changes via _extra_changes()

  9. Add metadata via _plan_meta()

  10. Create and return a Plan (or None if no changes)

Parameters:
  • desired (octodns.zone.Zone) – The desired zone state to sync to this provider.

  • processors (list[octodns.processor.base.BaseProcessor]) – List of processors to run during planning.

  • lenient (bool) – When True, relaxed validation rules should be applied by processors when modifying zone records.

Returns:

A Plan containing the computed changes, or None if no changes are needed.

Return type:

octodns.provider.plan.Plan or None

See also

apply(plan)[source]

Apply the planned changes to the provider.

This is the main apply method that submits the approved plan to the provider’s backend. If apply_disabled is True, this method does nothing and returns 0.

Parameters:

plan (octodns.provider.plan.Plan) – The plan containing changes to apply.

Returns:

The number of changes that were applied.

Return type:

int

See also

_apply(plan)[source]

Actually submit the changes to the provider’s backend.

This is an abstract method that must be implemented by all provider subclasses. It should take the changes in the plan and apply them to the provider’s API or backend system.

Parameters:

plan (octodns.provider.plan.Plan) – The plan containing changes to apply.

Raises:

NotImplementedError – This base class method must be overridden by subclasses.

Important

  • Must implement the actual logic to submit changes to the provider.

  • Should handle errors appropriately (log, raise exceptions, etc.).

  • May apply changes in any order that makes sense for the provider with as much safety as possible given the API methods available. Often the order of changes should apply deletes before adds to avoid comflicts during type changes, specidically CNAME <-> other types. If the provider’s API supports batching or atomic changes they should be used.

  • Should be idempotent where possible.