Skip to content

Add .load() class-method to DiffSyncModel #257

Description

@jamesharr

Environment

  • DiffSync version: 1.9.0

Proposed Functionality

This change proposes to 1) add a load() class-method to DiffSyncModel and 2) augments DiffSync.load() such that it will call each model's .load() method with whatever is passed in.

Key benefits:

  1. DiffSyncModel has always felt incomplete with only create/update/delete.
  2. It's a common pattern in code that I have written to have a .from_xyz() class-method to transform data. Adding it to diffsync would give it a more official location.
  3. The design of this API would support both two methods of loading data: a) each model calls an API to load code it needs b) there is one large call to load ALL the data, and each model handles interpreting the data, such as with GraphQL.
  4. Additional parameters, such as filtering criteria, could be passed to DiffSyncModel.load()

Use Case

# DiffSync modificationsclassDiffSyncModel:
@classmethoddefload(cls, diffsync: DiffSyncModel, *args, **kwargs):
pass# no-opclassDiffSync:
defload(self, *args, **kwargs):
# Pass all arguments to per-model flagsformodel_nameinself.store.get_all_model_names():
model_cls=getattr(self, model_name)
model_cls.load(*args, diffsync=self, **kwargs)
# Example user-code 1 - each model loads its own dataclassLocation(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, nb: pynautobot.api):
fornb_locationinnb.dcim.locations.filter():
diffsync.add(cls(name=nb_location.name, ...))
classDevice(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, nb: pynautobot.api):
fornb_deviceinnb.dcim.devices.all():
diffsync.add(cls(name=nb_device.name, ...))
classMyBackend(DiffSync):
... utilizesdefaultbackenddefmain():
be1=MyBackend()
be1.load(nb=pynautobot.api(...))
# Example user-code 2 - each model loads its own data, with filter criteria being passed alongclassLocation(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, nb: pynautobot.api, tags: List[str]):
fornb_locationinnb.dcim.locations.filter(tags=tags):
diffsync.add(cls(name=nb_location.name, ...))
classDevice(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, nb: pynautobot.api, tags: List[str]):
fornb_deviceinnb.dcim.devices.filter(tags=tags):
diffsync.add(cls(name=nb_device.name, ...))
classMyBackend(DiffSync):
... utilizesdefaultbackenddefmain():
be1=MyBackend()
be1.load(nb=pynautobot.api(...), tags=["US", "Europe"])
# Example user-code 3 - Backend handles data retrieval, models handle transformationclassLocation(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, graphql: GraphQLRecord):
fornb_locationingraphql.json["data"]["locations"]
diffsync.add(cls(name=nb_location["name"], ...))
classDevice(DiffSyncModel):
...
@classmethoddefload(cls, diffsync: DiffSyncModel, graphql: GraphQLRecord):
fornb_deviceingraphql.json["data"]["devices"]
diffsync.add(cls(name=nb_device["name"], ...))
classMyBackend(DiffSync):
defload(self):
nb=pynautobot.api(...)
result=nb.graphql.query("query { devices { name } locations { name } }")
super().load(graphql=result)
defmain():
be1=MyBackend()
be1.load()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions