From 60fbe2df3a9d9dbf0aeab0f60a084f7114fbf2c5 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Sun, 24 Apr 2022 16:31:14 +0200 Subject: [PATCH 01/19] Update example05 --- examples/05-nautobot-peeringdb/README.md | 38 +++++---- .../05-nautobot-peeringdb/adapter_nautobot.py | 83 +++++++------------ .../05-nautobot-peeringdb/docker-compose.yml | 14 ++++ examples/05-nautobot-peeringdb/dockerfile | 15 ++++ examples/05-nautobot-peeringdb/main.py | 17 +++- .../05-nautobot-peeringdb/requirements.txt | 1 + 6 files changed, 95 insertions(+), 73 deletions(-) create mode 100644 examples/05-nautobot-peeringdb/docker-compose.yml create mode 100644 examples/05-nautobot-peeringdb/dockerfile diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index 60c0f170..1621baa8 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -6,7 +6,7 @@ The goal of this example is to synchronize some data from [PeeringDB](https://ww In Peering DB there is a model that defines a `Facility` and you can get information about the actual data center and the city where it is placed. In Nautobot, this information could be mapped to the `Region` and `Site` models, where `Region` can define hierarchy. For instance, Barcelona is in Spain and Spain is in Europe, and all of them are `Regions`. And, finally, the actual datacenter will refer to the `Region` where it is placed. -Because of the nature of the demo, we will focus on syncing from PeeringDB to Nautobot (we can assume that PeeringDB is the authoritative System of Record) and we will skip the `delete` part of the `diffsync` library. +Because of the nature of the demo, we will focus on syncing from PeeringDB to Nautobot (we can assume that PeeringDB is the authoritative System of Record) and we will skip the `delete` part of the `diffsync` library, using diffsync flags. We have 3 files: @@ -16,12 +16,14 @@ We have 3 files: > The source code for this example is in Github in the [examples/05-nautobot-peeringdb/](https://github.com/networktocode/diffsync/tree/main/examples/05-nautobot-peeringdb) directory. -## Install dependencies +## Set up local docker environment ```bash -python3 -m venv .venv -source .venv/bin/activate -pip3 install -r requirements.txt +$ git clone https://github.com/networktocode/diffsync.git + +$ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d + +$ docker exec -it 05-nautobot-peeringdb_example_1 bash ``` ## Run it interactively @@ -30,20 +32,28 @@ pip3 install -r requirements.txt from IPython import embed embed(colors="neutral") -# Import Adapters -from diffsync.enum import DiffSyncFlags +import uuid +# Import Adapters from adapter_nautobot import NautobotRemote from adapter_peeringdb import PeeringDB +from diffsync.enum import DiffSyncFlags +from diffsync.store.redis import RedisStore + +REDIS_HOST = "redis" +PEERING_DB_IX_ID = 62 +NAUTOBOT_URL = "https://demo.nautobot.com" +NAUTOBOT_TOKEN = "a" * 40 + +store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) +store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) + # Initialize PeeringDB adapter, using CATNIX id for demonstration -peeringdb = PeeringDB(ix_id=62) +peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) # Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) -nautobot = NautobotRemote( - url="https://demo.nautobot.com", - token="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -) +nautobot = NautobotRemote(url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, internal_storage_engine=store_two) # nosec # Load PeeringDB info into the adapter peeringdb.load() @@ -55,9 +65,9 @@ peeringdb.dict() nautobot.load() # Let's diffsync do it's magic -diff = nautobot.diff_from(peeringdb) +diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) -# Quick summary of the expected changes (remember that delete ones are dry-run) +# Quick summary of the expected changes diff.summary() # Execute the synchronization diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index e86597e0..e36fd99e 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -1,13 +1,13 @@ """Diffsync adapter class for Nautobot.""" # pylint: disable=import-error,no-name-in-module import os -import requests +import pynautobot from models import RegionModel, SiteModel from diffsync import DiffSync NAUTOBOT_URL = os.getenv("NAUTOBOT_URL", "https://demo.nautobot.com") -NAUTOBOT_TOKEN = os.getenv("NAUTOBOT_TOKEN", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") +NAUTOBOT_TOKEN = os.getenv("NAUTOBOT_TOKEN", 40 * "a") class RegionNautobotModel(RegionModel): @@ -30,7 +30,9 @@ def create(cls, diffsync, ids, attrs): data["description"] = attrs["description"] if attrs["parent_name"]: data["parent"] = str(diffsync.get(diffsync.region, attrs["parent_name"]).pk) - diffsync.post("/api/dcim/regions/", data) + + diffsync.nautobot_api.dcim.regions.create(**data) + return super().create(diffsync, ids=ids, attrs=attrs) def update(self, attrs): @@ -39,6 +41,7 @@ def update(self, attrs): Args: attrs (dict): Updated values for this record's _attributes """ + region = self.diffsync.nautobot_api.dcim.regions.get(name=self.name) data = {} if "slug" in attrs: data["slug"] = attrs["slug"] @@ -46,15 +49,17 @@ def update(self, attrs): data["description"] = attrs["description"] if "parent_name" in attrs: if attrs["parent_name"]: - data["parent"] = str(self.diffsync.get(self.diffsync.region, attrs["parent_name"]).pk) + data["parent"] = str(self.diffsync.get(self.diffsync.region, attrs["parent_name"]).name) else: data["parent"] = None - self.diffsync.patch(f"/api/dcim/regions/{self.pk}/", data) + + region.update(data=data) + return super().update(attrs) def delete(self): # pylint: disable= useless-super-delegation """Delete an existing Region record from remote Nautobot.""" - # self.diffsync.delete(f"/api/dcim/regions/{self.pk}/") + # Not implemented return super().delete() @@ -70,17 +75,14 @@ def create(cls, diffsync, ids, attrs): ids (dict): Initial values for this model's _identifiers attrs (dict): Initial values for this model's _attributes """ - diffsync.post( - "/api/dcim/sites/", - { - "name": ids["name"], - "slug": attrs["slug"], - "description": attrs["description"], - "status": attrs["status_slug"], - "region": {"name": attrs["region_name"]} if attrs["region_name"] else None, - "latitude": attrs["latitude"], - "longitude": attrs["longitude"], - }, + diffsync.nautobot_api.dcim.sites.create( + name=ids["name"], + slug=attrs["slug"], + description=attrs["description"], + status=attrs["status_slug"], + region={"name": attrs["region_name"]} if attrs["region_name"] else None, + latitude=attrs["latitude"], + longitude=attrs["longitude"], ) return super().create(diffsync, ids=ids, attrs=attrs) @@ -90,6 +92,8 @@ def update(self, attrs): Args: attrs (dict): Updated values for this record's _attributes """ + site = self.diffsync.nautobot_api.dcim.sites.get(name=self.name) + data = {} if "slug" in attrs: data["slug"] = attrs["slug"] @@ -106,12 +110,14 @@ def update(self, attrs): data["latitude"] = attrs["latitude"] if "longitude" in attrs: data["longitude"] = attrs["longitude"] - self.diffsync.patch(f"/api/dcim/sites/{self.pk}/", data) + + site.update(data=data) + return super().update(attrs) def delete(self): # pylint: disable= useless-super-delegation """Delete an existing Site record from remote Nautobot.""" - # self.diffsync.delete(f"/api/dcim/sites/{self.pk}/") + # Not implemented return super().delete() @@ -136,21 +142,11 @@ def __init__(self, *args, url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, **kwargs): super().__init__(*args, **kwargs) if not url or not token: raise ValueError("Both url and token must be specified!") - self.url = url - self.token = token - self.headers = { - "Accept": "application/json", - "Authorization": f"Token {self.token}", - } + self.nautobot_api = pynautobot.api(url=url, token=token) def load(self): """Load Region and Site data from the remote Nautobot instance.""" - region_data = requests.get(f"{self.url}/api/dcim/regions/", headers=self.headers, params={"limit": 0}).json() - regions = region_data["results"] - while region_data["next"]: - region_data = requests.get(region_data["next"], headers=self.headers, params={"limit": 0}).json() - regions.extend(region_data["results"]) - + regions = self.nautobot_api.dcim.regions.all() for region_entry in regions: region = self.region( name=region_entry["name"], @@ -161,12 +157,7 @@ def load(self): ) self.add(region) - site_data = requests.get(f"{self.url}/api/dcim/sites/", headers=self.headers, params={"limit": 0}).json() - sites = site_data["results"] - while site_data["next"]: - site_data = requests.get(site_data["next"], headers=self.headers, params={"limit": 0}).json() - sites.extend(site_data["results"]) - + sites = self.nautobot_api.dcim.sites.all() for site_entry in sites: site = self.site( name=site_entry["name"], @@ -179,21 +170,3 @@ def load(self): pk=site_entry["id"], ) self.add(site) - - def post(self, path, data): - """Send an appropriately constructed HTTP POST request.""" - response = requests.post(f"{self.url}{path}", headers=self.headers, json=data) - response.raise_for_status() - return response - - def patch(self, path, data): - """Send an appropriately constructed HTTP PATCH request.""" - response = requests.patch(f"{self.url}{path}", headers=self.headers, json=data) - response.raise_for_status() - return response - - def delete(self, path): - """Send an appropriately constructed HTTP DELETE request.""" - response = requests.delete(f"{self.url}{path}", headers=self.headers) - response.raise_for_status() - return response diff --git a/examples/05-nautobot-peeringdb/docker-compose.yml b/examples/05-nautobot-peeringdb/docker-compose.yml new file mode 100644 index 00000000..5a8c97e1 --- /dev/null +++ b/examples/05-nautobot-peeringdb/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.8" +services: + example: + build: + context: "./" + dockerfile: "Dockerfile" + tty: true + depends_on: + redis: + condition: "service_started" + volumes: + - "./:/local" + redis: + image: "redis:6-alpine" diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile new file mode 100644 index 00000000..7e80de25 --- /dev/null +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -0,0 +1,15 @@ +ARG PYTHON_VER=3.8.10 + +FROM python:${PYTHON_VER}-slim + +RUN apt-get update \ + && apt-get install -y --no-install-recommends git \ + && apt-get purge -y --auto-remove \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /local +COPY . /local + +RUN pip install --upgrade pip \ + && python -m pip install git+https://github.com/networktocode/diffsync.git@redis \ + && pip install -r requirements.txt diff --git a/examples/05-nautobot-peeringdb/main.py b/examples/05-nautobot-peeringdb/main.py index c2cb7943..942bf3a1 100644 --- a/examples/05-nautobot-peeringdb/main.py +++ b/examples/05-nautobot-peeringdb/main.py @@ -1,17 +1,26 @@ """Main.py.""" +import uuid # Import Adapters from adapter_nautobot import NautobotRemote from adapter_peeringdb import PeeringDB from diffsync.enum import DiffSyncFlags +from diffsync.store.redis import RedisStore # pylint: disable=no-name-in-module,import-error +REDIS_HOST = "redis" +PEERING_DB_IX_ID = 62 +NAUTOBOT_URL = "https://demo.nautobot.com" +NAUTOBOT_TOKEN = "a" * 40 + +store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) +store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) # Initialize PeeringDB adapter, using CATNIX id for demonstration -peeringdb = PeeringDB(ix_id=62) +peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) # Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) -nautobot = NautobotRemote(url="https://demo.nautobot.com", token="a" * 40) # nosec +nautobot = NautobotRemote(url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, internal_storage_engine=store_two) # nosec # Load PeeringDB info into the adapter peeringdb.load() @@ -23,9 +32,9 @@ nautobot.load() # Let's diffsync do it's magic -diff = nautobot.diff_from(peeringdb) +diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) -# Quick summary of the expected changes (remember that delete ones are dry-run) +# Quick summary of the expected changes diff.summary() # Execute the synchronization diff --git a/examples/05-nautobot-peeringdb/requirements.txt b/examples/05-nautobot-peeringdb/requirements.txt index 84af760c..dec561dd 100644 --- a/examples/05-nautobot-peeringdb/requirements.txt +++ b/examples/05-nautobot-peeringdb/requirements.txt @@ -3,3 +3,4 @@ python-slugify pycountry requests IPython +pynautobot From 4b04776f4b830bfa65ae3b837e810583acb8a487 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 2 May 2022 10:13:02 +0200 Subject: [PATCH 02/19] Use site as children --- examples/05-nautobot-peeringdb/adapter_nautobot.py | 5 ++++- examples/05-nautobot-peeringdb/adapter_peeringdb.py | 5 +++-- examples/05-nautobot-peeringdb/models.py | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index e36fd99e..66f9e741 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -129,7 +129,7 @@ class NautobotRemote(DiffSync): site = SiteNautobotModel # Top-level class labels, i.e. those classes that are handled directly rather than as children of other models - top_level = ("region", "site") + top_level = ["region"] def __init__(self, *args, url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, **kwargs): """Instantiate this class, but do not load data immediately from the remote system. @@ -170,3 +170,6 @@ def load(self): pk=site_entry["id"], ) self.add(site) + if site_entry["region"]: + region = self.get(self.region, site_entry["region"]["name"]) + region.add_child(site) diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index 0bd6616e..c2f715c3 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -19,7 +19,7 @@ class PeeringDB(DiffSync): site = SiteModel # Top-level class labels, i.e. those classes that are handled directly rather than as children of other models - top_level = ("region", "site") + top_level = ["region"] def __init__(self, *args, ix_id, **kwargs): """Initialize the PeeringDB adapter.""" @@ -33,7 +33,7 @@ def load(self): for fac in ix_data["data"][0]["fac_set"]: # PeeringDB has no Region entity, so we must avoid duplicates try: - self.get(self.region, fac["city"]) + region = self.get(self.region, fac["city"]) except ObjectNotFound: # Use pycountry to translate the country code (like "DE") to a country name (like "Germany") parent_name = pycountry.countries.get(alpha_2=fac["country"]).name @@ -65,3 +65,4 @@ def load(self): pk=fac["id"], ) self.add(site) + region.add_child(site) diff --git a/examples/05-nautobot-peeringdb/models.py b/examples/05-nautobot-peeringdb/models.py index 063ef1f6..2fecb044 100644 --- a/examples/05-nautobot-peeringdb/models.py +++ b/examples/05-nautobot-peeringdb/models.py @@ -1,5 +1,5 @@ """DiffSyncModel subclasses for Nautobot-PeeringDB data sync.""" -from typing import Optional, Union +from typing import Optional, Union, List from uuid import UUID from diffsync import DiffSyncModel @@ -16,12 +16,14 @@ class RegionModel(DiffSyncModel): "description", "parent_name", ) + _children = {"site": "sites"} # Data type declarations for all identifiers and attributes name: str slug: str description: Optional[str] parent_name: Optional[str] # may be None + sites: List = [] # Not in _attributes or _identifiers, hence not included in diff calculations pk: Optional[UUID] From 5110a0d4571684ec7a72064200d56e513a8cb7ca Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 2 May 2022 11:55:31 +0200 Subject: [PATCH 03/19] Add update after adding children --- examples/05-nautobot-peeringdb/adapter_nautobot.py | 1 + examples/05-nautobot-peeringdb/adapter_peeringdb.py | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index 66f9e741..6fbfeaee 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -173,3 +173,4 @@ def load(self): if site_entry["region"]: region = self.get(self.region, site_entry["region"]["name"]) region.add_child(site) + self.update(region) diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index c2f715c3..e537379f 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -66,3 +66,4 @@ def load(self): ) self.add(site) region.add_child(site) + self.update(region) From 9a5ae11f41ddb1eee13801dc8ed41cd80d71459d Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 2 May 2022 12:14:24 +0200 Subject: [PATCH 04/19] Add pylint disable until Redis code is in --- examples/05-nautobot-peeringdb/adapter_nautobot.py | 2 +- examples/05-nautobot-peeringdb/adapter_peeringdb.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index 6fbfeaee..91be09b4 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -173,4 +173,4 @@ def load(self): if site_entry["region"]: region = self.get(self.region, site_entry["region"]["name"]) region.add_child(site) - self.update(region) + self.update(region) # pylint: disable=no-member diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index e537379f..e5753da6 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -66,4 +66,4 @@ def load(self): ) self.add(site) region.add_child(site) - self.update(region) + self.update(region) # pylint: disable=no-member From 66e8af0753c449327f03f8baafcb77a0cdfc3c08 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Sun, 8 May 2022 17:51:22 +0200 Subject: [PATCH 05/19] Update example --- examples/05-nautobot-peeringdb/README.md | 55 ++---------------------- examples/05-nautobot-peeringdb/main.py | 12 +++--- 2 files changed, 9 insertions(+), 58 deletions(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index 1621baa8..3cc64b44 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -4,15 +4,15 @@ The goal of this example is to synchronize some data from [PeeringDB](https://www.peeringdb.com/), that as the name suggests is a DB where peering entities define their facilities and presence to facilitate peering, towards [Nautobot Demo](https://demo.nautobot.com/) that is a always on demo service for [Nautobot](https://nautobot.readthedocs.io/), an open source Source of Truth. -In Peering DB there is a model that defines a `Facility` and you can get information about the actual data center and the city where it is placed. In Nautobot, this information could be mapped to the `Region` and `Site` models, where `Region` can define hierarchy. For instance, Barcelona is in Spain and Spain is in Europe, and all of them are `Regions`. And, finally, the actual datacenter will refer to the `Region` where it is placed. +In Peering DB there is a model that defines a `Facility` and you can get information about the actual data center and the city where it is placed. In Nautobot, this information could be mapped to the `Region` and `Site` models, where `Region` can depend from other `Region` and also contain `Site` as children. For instance, Barcelona is in Spain and Spain is in Europe, and all of them are `Regions`. And, finally, the actual datacenter will refer to the `Region` where it is placed. -Because of the nature of the demo, we will focus on syncing from PeeringDB to Nautobot (we can assume that PeeringDB is the authoritative System of Record) and we will skip the `delete` part of the `diffsync` library, using diffsync flags. +Because of the nature of the demo, we will focus on syncing from PeeringDB to Nautobot (we assume that PeeringDB is the authoritative System of Record) and we will skip the `delete` part of the `diffsync` library, using diffsync flags. We have 3 files: - `models.py`: defines the reference models that we will use: `RegionMode` and `SiteModel` - `adapter_peeringdb.py`: defines the PeeringDB adapter to translate via `load()` the data from PeeringDB into the reference models commented above. Notice that we don't define CRUD methods because we will sync from it (no to it) -- `adapter_nautobot.py`: deifnes the Nautobot adapter with the `load()` and the CRUD methods +- `adapter_nautobot.py`: defines the Nautobot adapter with the `load()` and the CRUD methods > The source code for this example is in Github in the [examples/05-nautobot-peeringdb/](https://github.com/networktocode/diffsync/tree/main/examples/05-nautobot-peeringdb) directory. @@ -25,52 +25,3 @@ $ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d $ docker exec -it 05-nautobot-peeringdb_example_1 bash ``` - -## Run it interactively - -```python -from IPython import embed -embed(colors="neutral") - -import uuid - -# Import Adapters -from adapter_nautobot import NautobotRemote -from adapter_peeringdb import PeeringDB - -from diffsync.enum import DiffSyncFlags -from diffsync.store.redis import RedisStore - -REDIS_HOST = "redis" -PEERING_DB_IX_ID = 62 -NAUTOBOT_URL = "https://demo.nautobot.com" -NAUTOBOT_TOKEN = "a" * 40 - -store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) -store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) - -# Initialize PeeringDB adapter, using CATNIX id for demonstration -peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) - -# Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) -nautobot = NautobotRemote(url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, internal_storage_engine=store_two) # nosec - -# Load PeeringDB info into the adapter -peeringdb.load() - -# We can check the data that has been imported, some as `site` and some as `region` (with the parent relationships) -peeringdb.dict() - -# Load Nautobot info into the adapter -nautobot.load() - -# Let's diffsync do it's magic -diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) - -# Quick summary of the expected changes -diff.summary() - -# Execute the synchronization -nautobot.sync_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) - -``` diff --git a/examples/05-nautobot-peeringdb/main.py b/examples/05-nautobot-peeringdb/main.py index 942bf3a1..fbc6a459 100644 --- a/examples/05-nautobot-peeringdb/main.py +++ b/examples/05-nautobot-peeringdb/main.py @@ -1,5 +1,5 @@ """Main.py.""" -import uuid +from uuid import uuid4 # Import Adapters from adapter_nautobot import NautobotRemote @@ -9,14 +9,14 @@ from diffsync.store.redis import RedisStore # pylint: disable=no-name-in-module,import-error REDIS_HOST = "redis" -PEERING_DB_IX_ID = 62 +PEERING_DB_IX_ID = 62 # CATNIX ID NAUTOBOT_URL = "https://demo.nautobot.com" NAUTOBOT_TOKEN = "a" * 40 -store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) -store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) +store_one = RedisStore(host=REDIS_HOST, id=uuid4()) +store_two = RedisStore(host=REDIS_HOST, id=uuid4()) -# Initialize PeeringDB adapter, using CATNIX id for demonstration +# Initialize PeeringDB adapter peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) # Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) @@ -28,7 +28,7 @@ # We can check the data that has been imported, some as `site` and some as `region` (with the parent relationships) peeringdb.dict() -# Load Nautobot info into the adapter +# Load Nautobot info into the Nautobot adapter nautobot.load() # Let's diffsync do it's magic From 30c4998157a0a223f4f68fe101bf9d6ae0c2167e Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 16 May 2022 14:28:36 +0200 Subject: [PATCH 06/19] simplify --- docs/source/examples/index.rst | 1 + examples/05-nautobot-peeringdb/main.py | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index 4bd1043c..173f7418 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -8,3 +8,4 @@ For each example, the complete source code is `available in Github Date: Fri, 20 May 2022 09:56:38 +0200 Subject: [PATCH 07/19] wip --- examples/05-nautobot-peeringdb/README.md | 2 +- examples/05-nautobot-peeringdb/dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index 3cc64b44..a67b4a91 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -21,7 +21,7 @@ We have 3 files: ```bash $ git clone https://github.com/networktocode/diffsync.git -$ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d +$ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d --build $ docker exec -it 05-nautobot-peeringdb_example_1 bash ``` diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile index 7e80de25..6b8666d0 100644 --- a/examples/05-nautobot-peeringdb/dockerfile +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -11,5 +11,5 @@ WORKDIR /local COPY . /local RUN pip install --upgrade pip \ - && python -m pip install git+https://github.com/networktocode/diffsync.git@redis \ + && python -m pip install -e git+https://github.com/networktocode/diffsync.git@redis#egg=diffsync[redis] \ && pip install -r requirements.txt From e2b3732ca97d5143879ec97f97b137cb511a0932 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Fri, 20 May 2022 10:04:54 +0200 Subject: [PATCH 08/19] wip --- examples/05-nautobot-peeringdb/dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile index 6b8666d0..625a4142 100644 --- a/examples/05-nautobot-peeringdb/dockerfile +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -11,5 +11,5 @@ WORKDIR /local COPY . /local RUN pip install --upgrade pip \ - && python -m pip install -e git+https://github.com/networktocode/diffsync.git@redis#egg=diffsync[redis] \ + && python -m pip install git+https://github.com/networktocode/diffsync.git@redis#egg=diffsync[redis] \ && pip install -r requirements.txt From 6b062814333d46cc74f2d657292a2d6a66ff7886 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Sun, 8 May 2022 17:51:22 +0200 Subject: [PATCH 09/19] Update example --- docs/source/examples/index.rst | 1 + examples/05-nautobot-peeringdb/README.md | 57 ++--------------------- examples/05-nautobot-peeringdb/dockerfile | 2 +- examples/05-nautobot-peeringdb/main.py | 11 ++--- 4 files changed, 11 insertions(+), 60 deletions(-) diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index 4bd1043c..173f7418 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -8,3 +8,4 @@ For each example, the complete source code is `available in Github The source code for this example is in Github in the [examples/05-nautobot-peeringdb/](https://github.com/networktocode/diffsync/tree/main/examples/05-nautobot-peeringdb) directory. @@ -21,56 +21,7 @@ We have 3 files: ```bash $ git clone https://github.com/networktocode/diffsync.git -$ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d +$ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d --build $ docker exec -it 05-nautobot-peeringdb_example_1 bash ``` - -## Run it interactively - -```python -from IPython import embed -embed(colors="neutral") - -import uuid - -# Import Adapters -from adapter_nautobot import NautobotRemote -from adapter_peeringdb import PeeringDB - -from diffsync.enum import DiffSyncFlags -from diffsync.store.redis import RedisStore - -REDIS_HOST = "redis" -PEERING_DB_IX_ID = 62 -NAUTOBOT_URL = "https://demo.nautobot.com" -NAUTOBOT_TOKEN = "a" * 40 - -store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) -store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) - -# Initialize PeeringDB adapter, using CATNIX id for demonstration -peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) - -# Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) -nautobot = NautobotRemote(url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, internal_storage_engine=store_two) # nosec - -# Load PeeringDB info into the adapter -peeringdb.load() - -# We can check the data that has been imported, some as `site` and some as `region` (with the parent relationships) -peeringdb.dict() - -# Load Nautobot info into the adapter -nautobot.load() - -# Let's diffsync do it's magic -diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) - -# Quick summary of the expected changes -diff.summary() - -# Execute the synchronization -nautobot.sync_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) - -``` diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile index 7e80de25..625a4142 100644 --- a/examples/05-nautobot-peeringdb/dockerfile +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -11,5 +11,5 @@ WORKDIR /local COPY . /local RUN pip install --upgrade pip \ - && python -m pip install git+https://github.com/networktocode/diffsync.git@redis \ + && python -m pip install git+https://github.com/networktocode/diffsync.git@redis#egg=diffsync[redis] \ && pip install -r requirements.txt diff --git a/examples/05-nautobot-peeringdb/main.py b/examples/05-nautobot-peeringdb/main.py index 942bf3a1..ad78598a 100644 --- a/examples/05-nautobot-peeringdb/main.py +++ b/examples/05-nautobot-peeringdb/main.py @@ -1,5 +1,4 @@ """Main.py.""" -import uuid # Import Adapters from adapter_nautobot import NautobotRemote @@ -9,14 +8,14 @@ from diffsync.store.redis import RedisStore # pylint: disable=no-name-in-module,import-error REDIS_HOST = "redis" -PEERING_DB_IX_ID = 62 +PEERING_DB_IX_ID = 62 # CATNIX ID NAUTOBOT_URL = "https://demo.nautobot.com" NAUTOBOT_TOKEN = "a" * 40 -store_one = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) -store_two = RedisStore(host=REDIS_HOST, id=uuid.uuid4()) +store_one = RedisStore(host=REDIS_HOST) +store_two = RedisStore(host=REDIS_HOST) -# Initialize PeeringDB adapter, using CATNIX id for demonstration +# Initialize PeeringDB adapter peeringdb = PeeringDB(ix_id=PEERING_DB_IX_ID, internal_storage_engine=store_one) # Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) @@ -28,7 +27,7 @@ # We can check the data that has been imported, some as `site` and some as `region` (with the parent relationships) peeringdb.dict() -# Load Nautobot info into the adapter +# Load Nautobot info into the Nautobot adapter nautobot.load() # Let's diffsync do it's magic From 7554162f078bab72bdba63b6beb348384ba66531 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Wed, 25 May 2022 19:23:05 +0200 Subject: [PATCH 10/19] Take redis from main --- .gitignore | 3 +++ examples/05-nautobot-peeringdb/README.md | 13 +++++++++++++ examples/05-nautobot-peeringdb/adapter_peeringdb.py | 8 +++++++- examples/05-nautobot-peeringdb/creds.example.env | 1 + examples/05-nautobot-peeringdb/docker-compose.yml | 2 ++ examples/05-nautobot-peeringdb/dockerfile | 2 +- 6 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 examples/05-nautobot-peeringdb/creds.example.env diff --git a/.gitignore b/.gitignore index 78344b0b..72211f93 100644 --- a/.gitignore +++ b/.gitignore @@ -289,3 +289,6 @@ fabric.properties ## Sphinx Documentation ## docs/build + +## Secrets +creds.env diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index a67b4a91..b49530d3 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -16,6 +16,19 @@ We have 3 files: > The source code for this example is in Github in the [examples/05-nautobot-peeringdb/](https://github.com/networktocode/diffsync/tree/main/examples/05-nautobot-peeringdb) directory. +## Get PeeringDB API Key + +To ensure a good performance from PeeringDB API, you should request a provide an API Key: https://docs.peeringdb.com/howto/api_keys/ + +Then, copy the example `creds.example.env` into `creds.env`, and place your new API Key. + +```bash +$ cp examples/05-nautobot-peeringdb/creds.example.env examples/05-nautobot-peeringdb/creds.env + +``` + +> Without API Key it could also work, but it could fail due API rate limiting. + ## Set up local docker environment ```bash diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index e5753da6..75596e65 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -1,6 +1,7 @@ """Diffsync adapter class for PeeringDB.""" # pylint: disable=import-error,no-name-in-module import requests +import os from slugify import slugify import pycountry from models import RegionModel, SiteModel @@ -9,6 +10,7 @@ PEERINGDB_URL = "https://peeringdb.com/" +peeringdb_api_key = os.environ.get("PEERINGDB_API_KEY", "").strip() class PeeringDB(DiffSync): @@ -28,7 +30,11 @@ def __init__(self, *args, ix_id, **kwargs): def load(self): """Load data via from PeeringDB.""" - ix_data = requests.get(f"{PEERINGDB_URL}/api/ix/{self.ix_id}").json() + headers = {} + if peeringdb_api_key: + headers["Authorization"] = f"Api-Key {peeringdb_api_key}" + + ix_data = requests.get(f"{PEERINGDB_URL}/api/ix/{self.ix_id}", headers=headers).json() for fac in ix_data["data"][0]["fac_set"]: # PeeringDB has no Region entity, so we must avoid duplicates diff --git a/examples/05-nautobot-peeringdb/creds.example.env b/examples/05-nautobot-peeringdb/creds.example.env new file mode 100644 index 00000000..5e8ff7f4 --- /dev/null +++ b/examples/05-nautobot-peeringdb/creds.example.env @@ -0,0 +1 @@ +PEERINGDB_API_KEY="" diff --git a/examples/05-nautobot-peeringdb/docker-compose.yml b/examples/05-nautobot-peeringdb/docker-compose.yml index 5a8c97e1..01e90c89 100644 --- a/examples/05-nautobot-peeringdb/docker-compose.yml +++ b/examples/05-nautobot-peeringdb/docker-compose.yml @@ -10,5 +10,7 @@ services: condition: "service_started" volumes: - "./:/local" + env_file: + - "creds.env" redis: image: "redis:6-alpine" diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile index 625a4142..bd733384 100644 --- a/examples/05-nautobot-peeringdb/dockerfile +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -11,5 +11,5 @@ WORKDIR /local COPY . /local RUN pip install --upgrade pip \ - && python -m pip install git+https://github.com/networktocode/diffsync.git@redis#egg=diffsync[redis] \ + && python -m pip install git+https://github.com/networktocode/diffsync.git#egg=diffsync[redis] \ && pip install -r requirements.txt From 4888266c98d7ebe6139f20f5794aec6c05c55d9f Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Wed, 25 May 2022 19:30:47 +0200 Subject: [PATCH 11/19] imprort order --- examples/05-nautobot-peeringdb/adapter_peeringdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index 75596e65..dfae9178 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -1,7 +1,7 @@ """Diffsync adapter class for PeeringDB.""" # pylint: disable=import-error,no-name-in-module -import requests import os +import requests from slugify import slugify import pycountry from models import RegionModel, SiteModel From a15d3467deba3feb1b629d04018800fd798555ba Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Thu, 26 May 2022 06:05:02 +0200 Subject: [PATCH 12/19] yml --- examples/05-nautobot-peeringdb/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/05-nautobot-peeringdb/docker-compose.yml b/examples/05-nautobot-peeringdb/docker-compose.yml index 01e90c89..1315d3d7 100644 --- a/examples/05-nautobot-peeringdb/docker-compose.yml +++ b/examples/05-nautobot-peeringdb/docker-compose.yml @@ -1,3 +1,4 @@ +--- version: "3.8" services: example: From 614d1bdfdb3e00e854b04b65a442d69de55dc9c3 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Mon, 30 May 2022 18:57:54 +0200 Subject: [PATCH 13/19] update readme --- examples/05-nautobot-peeringdb/README.md | 39 ++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index b49530d3..e6856969 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -16,9 +16,9 @@ We have 3 files: > The source code for this example is in Github in the [examples/05-nautobot-peeringdb/](https://github.com/networktocode/diffsync/tree/main/examples/05-nautobot-peeringdb) directory. -## Get PeeringDB API Key +## Get PeeringDB API Key (optional) -To ensure a good performance from PeeringDB API, you should request a provide an API Key: https://docs.peeringdb.com/howto/api_keys/ +To ensure a good performance from PeeringDB API, you should provide an API Key: https://docs.peeringdb.com/howto/api_keys/ Then, copy the example `creds.example.env` into `creds.env`, and place your new API Key. @@ -38,3 +38,38 @@ $ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d --bu $ docker exec -it 05-nautobot-peeringdb_example_1 bash ``` + +## Interactive execution + +```python +from adapter_nautobot import NautobotRemote +from adapter_peeringdb import PeeringDB +from diffsync.enum import DiffSyncFlags +from diffsync.store.redis import RedisStore + +store_one = RedisStore(host="redis") +store_two = RedisStore(host="redis") + +peeringdb = PeeringDB( + ix_id=62, + internal_storage_engine=store_one +) + +nautobot = NautobotRemote( + url="https://demo.nautobot.com", + token="a" * 40, + internal_storage_engine=store_two +) + +peeringdb.load() + +peeringdb.dict() + +nautobot.load() + +diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) + +diff.summary() + +nautobot.sync_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) +``` From fb315054a6353d122ed30c5dd41ac5f6422381eb Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Wed, 8 Jun 2022 15:02:42 +0200 Subject: [PATCH 14/19] Use diffsync from pypi --- examples/05-nautobot-peeringdb/dockerfile | 1 - examples/05-nautobot-peeringdb/requirements.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/dockerfile index bd733384..26959b47 100644 --- a/examples/05-nautobot-peeringdb/dockerfile +++ b/examples/05-nautobot-peeringdb/dockerfile @@ -11,5 +11,4 @@ WORKDIR /local COPY . /local RUN pip install --upgrade pip \ - && python -m pip install git+https://github.com/networktocode/diffsync.git#egg=diffsync[redis] \ && pip install -r requirements.txt diff --git a/examples/05-nautobot-peeringdb/requirements.txt b/examples/05-nautobot-peeringdb/requirements.txt index dec561dd..06255a28 100644 --- a/examples/05-nautobot-peeringdb/requirements.txt +++ b/examples/05-nautobot-peeringdb/requirements.txt @@ -1,4 +1,4 @@ -diffsync +diffsync[redis] python-slugify pycountry requests From 31869c4e84359b83ad8ec4ee97d36378ddd1a3ed Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Fri, 10 Jun 2022 07:19:41 +0200 Subject: [PATCH 15/19] Apply suggestions from code review Co-authored-by: Glenn Matthews --- examples/05-nautobot-peeringdb/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index e6856969..c57927a7 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -27,7 +27,7 @@ $ cp examples/05-nautobot-peeringdb/creds.example.env examples/05-nautobot-peeri ``` -> Without API Key it could also work, but it could fail due API rate limiting. +> Without API Key it might also work, but it could fail due to API rate limiting. ## Set up local docker environment From 8ebab53fcf7322f0c307e1b03eedf2f5f69f3255 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Fri, 10 Jun 2022 07:33:17 +0200 Subject: [PATCH 16/19] Code review --- examples/05-nautobot-peeringdb/README.md | 2 -- examples/05-nautobot-peeringdb/adapter_nautobot.py | 9 ++------- examples/05-nautobot-peeringdb/adapter_peeringdb.py | 6 +++--- examples/05-nautobot-peeringdb/main.py | 2 +- examples/05-nautobot-peeringdb/requirements.txt | 2 +- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index c57927a7..a64b3ff7 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -32,8 +32,6 @@ $ cp examples/05-nautobot-peeringdb/creds.example.env examples/05-nautobot-peeri ## Set up local docker environment ```bash -$ git clone https://github.com/networktocode/diffsync.git - $ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d --build $ docker exec -it 05-nautobot-peeringdb_example_1 bash diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index 91be09b4..7970274d 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -1,15 +1,10 @@ """Diffsync adapter class for Nautobot.""" # pylint: disable=import-error,no-name-in-module -import os import pynautobot from models import RegionModel, SiteModel from diffsync import DiffSync -NAUTOBOT_URL = os.getenv("NAUTOBOT_URL", "https://demo.nautobot.com") -NAUTOBOT_TOKEN = os.getenv("NAUTOBOT_TOKEN", 40 * "a") - - class RegionNautobotModel(RegionModel): """Implementation of Region create/update/delete methods for updating remote Nautobot data.""" @@ -131,7 +126,7 @@ class NautobotRemote(DiffSync): # Top-level class labels, i.e. those classes that are handled directly rather than as children of other models top_level = ["region"] - def __init__(self, *args, url=NAUTOBOT_URL, token=NAUTOBOT_TOKEN, **kwargs): + def __init__(self, *args, url, token, **kwargs): """Instantiate this class, but do not load data immediately from the remote system. Args: @@ -173,4 +168,4 @@ def load(self): if site_entry["region"]: region = self.get(self.region, site_entry["region"]["name"]) region.add_child(site) - self.update(region) # pylint: disable=no-member + self.update(region) diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index dfae9178..08feb600 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -10,7 +10,7 @@ PEERINGDB_URL = "https://peeringdb.com/" -peeringdb_api_key = os.environ.get("PEERINGDB_API_KEY", "").strip() +PEERINGDB_API_KEY = os.environ.get("PEERINGDB_API_KEY", "").strip() class PeeringDB(DiffSync): @@ -31,8 +31,8 @@ def __init__(self, *args, ix_id, **kwargs): def load(self): """Load data via from PeeringDB.""" headers = {} - if peeringdb_api_key: - headers["Authorization"] = f"Api-Key {peeringdb_api_key}" + if PEERINGDB_API_KEY: + headers["Authorization"] = f"Api-Key {PEERINGDB_API_KEY}" ix_data = requests.get(f"{PEERINGDB_URL}/api/ix/{self.ix_id}", headers=headers).json() diff --git a/examples/05-nautobot-peeringdb/main.py b/examples/05-nautobot-peeringdb/main.py index ad78598a..6f011830 100644 --- a/examples/05-nautobot-peeringdb/main.py +++ b/examples/05-nautobot-peeringdb/main.py @@ -5,7 +5,7 @@ from adapter_peeringdb import PeeringDB from diffsync.enum import DiffSyncFlags -from diffsync.store.redis import RedisStore # pylint: disable=no-name-in-module,import-error +from diffsync.store.redis import RedisStore REDIS_HOST = "redis" PEERING_DB_IX_ID = 62 # CATNIX ID diff --git a/examples/05-nautobot-peeringdb/requirements.txt b/examples/05-nautobot-peeringdb/requirements.txt index 06255a28..dba2709e 100644 --- a/examples/05-nautobot-peeringdb/requirements.txt +++ b/examples/05-nautobot-peeringdb/requirements.txt @@ -1,4 +1,4 @@ -diffsync[redis] +diffsync[redis]>=1.5.0 python-slugify pycountry requests From 3bd0f6f696babc3baf3db7ab92e507e7a6ac41e5 Mon Sep 17 00:00:00 2001 From: Christian Adell Date: Wed, 15 Jun 2022 09:09:31 -0700 Subject: [PATCH 17/19] replace bash by python exec --- examples/05-nautobot-peeringdb/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/05-nautobot-peeringdb/README.md b/examples/05-nautobot-peeringdb/README.md index a64b3ff7..c2c58c02 100644 --- a/examples/05-nautobot-peeringdb/README.md +++ b/examples/05-nautobot-peeringdb/README.md @@ -34,7 +34,7 @@ $ cp examples/05-nautobot-peeringdb/creds.example.env examples/05-nautobot-peeri ```bash $ docker-compose -f examples/05-nautobot-peeringdb/docker-compose.yml up -d --build -$ docker exec -it 05-nautobot-peeringdb_example_1 bash +$ docker exec -it 05-nautobot-peeringdb_example_1 python ``` ## Interactive execution @@ -48,26 +48,34 @@ from diffsync.store.redis import RedisStore store_one = RedisStore(host="redis") store_two = RedisStore(host="redis") +# Initialize PeeringDB adapter, using CATNIX id for demonstration peeringdb = PeeringDB( ix_id=62, internal_storage_engine=store_one ) +# Initialize Nautobot adapter, pointing to the demo instance (it's also the default settings) nautobot = NautobotRemote( url="https://demo.nautobot.com", token="a" * 40, internal_storage_engine=store_two ) +# Load PeeringDB info into the adapter peeringdb.load() +# We can check the data that has been imported, some as `site` and some as `region` (with the parent relationships) peeringdb.dict() +# Load Nautobot info into the adapter nautobot.load() +# Let's diffsync do it's magic diff = nautobot.diff_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) +# Quick summary of the expected changes (remember that delete ones are dry-run) diff.summary() +# Execute the synchronization nautobot.sync_from(peeringdb, flags=DiffSyncFlags.SKIP_UNMATCHED_DST) ``` From 64cec66213421aeca5f414fc3dfafb5a786488e3 Mon Sep 17 00:00:00 2001 From: Glenn Matthews Date: Thu, 30 Jun 2022 13:29:41 -0400 Subject: [PATCH 18/19] Rename dockerfile to Dockerfile --- examples/05-nautobot-peeringdb/{dockerfile => Dockerfile} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/05-nautobot-peeringdb/{dockerfile => Dockerfile} (100%) diff --git a/examples/05-nautobot-peeringdb/dockerfile b/examples/05-nautobot-peeringdb/Dockerfile similarity index 100% rename from examples/05-nautobot-peeringdb/dockerfile rename to examples/05-nautobot-peeringdb/Dockerfile From f3948ad2d428963e745eb6b61561935dced51557 Mon Sep 17 00:00:00 2001 From: Glenn Matthews Date: Thu, 30 Jun 2022 14:16:48 -0400 Subject: [PATCH 19/19] Update docs source --- docs/source/api/diffsync.rst | 8 ++++++++ docs/source/api/diffsync.store.local.rst | 7 +++++++ docs/source/api/diffsync.store.redis.rst | 7 +++++++ docs/source/api/diffsync.store.rst | 14 ++++++++++++++ docs/source/examples/index.rst | 1 + docs/source/template/api/package.rst_t | 16 ++++++++-------- examples/06-ip-prefixes/README.md | 2 +- 7 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 docs/source/api/diffsync.store.local.rst create mode 100644 docs/source/api/diffsync.store.redis.rst create mode 100644 docs/source/api/diffsync.store.rst diff --git a/docs/source/api/diffsync.rst b/docs/source/api/diffsync.rst index 36349fc7..f0829933 100644 --- a/docs/source/api/diffsync.rst +++ b/docs/source/api/diffsync.rst @@ -16,3 +16,11 @@ API Reference diffsync.helpers diffsync.logging diffsync.utils + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + diffsync.store diff --git a/docs/source/api/diffsync.store.local.rst b/docs/source/api/diffsync.store.local.rst new file mode 100644 index 00000000..e6f342c6 --- /dev/null +++ b/docs/source/api/diffsync.store.local.rst @@ -0,0 +1,7 @@ +diffsync.store.local +==================== + +.. automodule:: diffsync.store.local + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/diffsync.store.redis.rst b/docs/source/api/diffsync.store.redis.rst new file mode 100644 index 00000000..64576153 --- /dev/null +++ b/docs/source/api/diffsync.store.redis.rst @@ -0,0 +1,7 @@ +diffsync.store.redis +==================== + +.. automodule:: diffsync.store.redis + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/diffsync.store.rst b/docs/source/api/diffsync.store.rst new file mode 100644 index 00000000..35638d29 --- /dev/null +++ b/docs/source/api/diffsync.store.rst @@ -0,0 +1,14 @@ +API Reference +============= + +.. automodule:: diffsync.store + :members: + :undoc-members: + :show-inheritance: + + +.. toctree:: + :maxdepth: 4 + + diffsync.store.local + diffsync.store.redis diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index 173f7418..d67609c7 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -9,3 +9,4 @@ For each example, the complete source code is `available in Github