Skip to content
This repository has been archived by the owner on Dec 1, 2023. It is now read-only.

Commit

Permalink
Merge pull request #92 from nautobot/release-v0.9.5
Browse files Browse the repository at this point in the history
Release v0.9.5
  • Loading branch information
pke11y authored May 11, 2022
2 parents 8f93d6a + 8018687 commit d4eaa3b
Show file tree
Hide file tree
Showing 20 changed files with 1,075 additions and 968 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Default owner(s) of all files in this repository
* @h4ndzdatm0ld
* @h4ndzdatm0ld @pke11y @chadell
2 changes: 2 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
---
ignore: |
/nautobot_ssot_ipfabric/.devcontainer/
extends: "default"
rules:
comments: "enable"
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


## v0.9.5 - 2022-05-11

### Added

- #89 - Add necessary assigned_object_type when assigned_object_id is defined.
- #85 - Migrate to ipfabric client library.

## v0.9.4 - 2022-01-26

### Added

- #76 - Refactor safe mode.
- #71 - Job name change.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ An [SSoT](https://blog.networktocode.com/post/nautobot-ssot-plugin/) plugin prov

## Build Status

| Branch | Status |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Branch | Status |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **main** | ![Build Status](https://github.com/nautobot/nautobot-plugin-ssot-ipfabric/actions/workflows/nautobot-ssot-ipfabric-ci.yml/badge.svg?branch=main) |
| **develop** | ![Build Status](https://github.com/nautobot/nautobot-plugin-ssot-ipfabric/actions/workflows/nautobot-ssot-ipfabric-ci.yml/badge.svg?branch=develop)|
| **develop** | ![Build Status](https://github.com/nautobot/nautobot-plugin-ssot-ipfabric/actions/workflows/nautobot-ssot-ipfabric-ci.yml/badge.svg?branch=develop) |

## Documentation

Expand Down Expand Up @@ -44,6 +44,8 @@ This plugin relies on user provided environment variables to interact with IP Fa
- `ipfabric_api_token` - API Token for IP Fabric
- `ipfabric_host` - IP Fabric URL
- `nautobot_host` - Nautobot URL (This is used to generate url links for chatops)
- `ipfabric_ssl_verify`- IP Fabric API SSL verification
- `ipfabric_timeout`- IP Fabric API timeout

Example `PLUGINS_CONFIG` to be updated in `nautobot_config.py` after successful installation. The chatops configuration is optional, but if you'd like to have the
ability to call the sync job through chatops, you will be required to configure it.
Expand All @@ -60,6 +62,8 @@ PLUGINS_CONFIG = {
"ipfabric_api_token": os.environ.get("IPFABRIC_API_TOKEN"),
"ipfabric_host": os.environ.get("IPFABRIC_HOST"),
"nautobot_host": os.environ.get("NAUTOBOT_HOST"),
"ipfabric_ssl_verify": os.environ.get("IPFABRIC_SSL_VERIFY"),
"ipfabric_timeout": os.environ.get("IPFABRIC_TIMEOUT"),
},
"nautobot_ssot": {"hide_example_jobs": True},
"nautobot_chatops_ipfabric": {
Expand Down Expand Up @@ -94,7 +98,7 @@ Below is a quick start guide if you're already familiar with the development env

#### Invoke

The [PyInvoke](http://www.pyinvoke.org/) library is used to provide some helper commands based on the environment. There are a few configuration parameters which can be passed to PyInvoke to override the default configuration:
The [PyInvoke](http://www.pyinvoke.org/) library is used to provide some helper commands based on the environment. There are a few configuration parameters which can be passed to PyInvoke to override the default configuration:

- `nautobot_ver`: the version of Nautobot to use as a base for any built docker containers (default: 1.1.4)
- `project_name`: the default docker compose project name (default: nautobot_ssot_ipfabric)
Expand All @@ -103,7 +107,7 @@ The [PyInvoke](http://www.pyinvoke.org/) library is used to provide some helper
- `compose_dir`: the full path to a directory containing the project compose files
- `compose_files`: a list of compose files applied in order (see [Multiple Compose files](https://docs.docker.com/compose/extends/#multiple-compose-files) for more information)

Using **PyInvoke** these configuration options can be overridden using [several methods](http://docs.pyinvoke.org/en/stable/concepts/configuration.html). Perhaps the simplest is simply setting an environment variable `INVOKE_NAUTOBOT_SSOT_IPFABRIC_VARIABLE_NAME` where `VARIABLE_NAME` is the variable you are trying to override. The only exception is `compose_files`, because it is a list it must be overridden in a yaml file. There is an example `invoke.yml` (`invoke.example.yml`) in this directory which can be used as a starting point.
Using **PyInvoke** these configuration options can be overridden using [several methods](http://docs.pyinvoke.org/en/stable/concepts/configuration.html). Perhaps the simplest is simply setting an environment variable `INVOKE_NAUTOBOT_SSOT_IPFABRIC_VARIABLE_NAME` where `VARIABLE_NAME` is the variable you are trying to override. The only exception is `compose_files`, because it is a list it must be overridden in a yaml file. There is an example `invoke.yml` (`invoke.example.yml`) in this directory which can be used as a starting point.

#### Local Poetry Development Environment

Expand Down
4 changes: 2 additions & 2 deletions development/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ARG PYTHON_VER
ARG NAUTOBOT_VER
ARG PYTHON_VER=3.8
ARG NAUTOBOT_VER="1.2.4"
FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER}

WORKDIR /source
Expand Down
3 changes: 1 addition & 2 deletions development/custom_logging_levels.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
custom_loggin_levels.py
"""Custom_loggin_levels.py.
Override logging level for specific modules.
Relies on PYTHONSTARTUP="custom_loggin_levels.py" in environment
Expand Down
2 changes: 1 addition & 1 deletion development/docker-compose.base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ x-nautobot-build: &nautobot-build
context: "../"
dockerfile: "development/Dockerfile"
x-nautobot-base: &nautobot-base
image: "nautobot-ssot-servicenow/nautobot:${NAUTOBOT_VER}-py${PYTHON_VER}"
image: "nautobot-ssot-ipfabric/nautobot:${NAUTOBOT_VER}-py${PYTHON_VER}"
env_file:
- "dev.env"
- "creds.env"
Expand Down
1 change: 1 addition & 0 deletions development/nautobot_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Nautobot Config file."""
#########################
# #
# Required settings #
Expand Down
18 changes: 0 additions & 18 deletions docs/changelog.md

This file was deleted.

5 changes: 4 additions & 1 deletion nautobot_ssot_ipfabric/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ class NautobotSSoTIPFabricConfig(PluginConfig):
required_settings = ["ipfabric_host", "ipfabric_api_token"]
min_version = "1.2.0"
max_version = "1.9999"
default_settings = {}
default_settings = {
"ipfabric_ssl_verify": False,
"ipfabric_timeout": 15,
}
caching_config = {}

def ready(self):
Expand Down
30 changes: 23 additions & 7 deletions nautobot_ssot_ipfabric/diffsync/adapter_ipfabric.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from diffsync import ObjectAlreadyExists
from django.conf import settings
from nautobot.dcim.models import Device
from nautobot.ipam.models import VLAN
from netutils.mac import mac_to_format

Expand All @@ -18,6 +19,9 @@
DEFAULT_DEVICE_ROLE = CONFIG.get("default_device_role", "Network Device")
DEFAULT_DEVICE_STATUS = CONFIG.get("default_device_status", "Active")

device_serial_max_length = Device._meta.get_field("serial").max_length
name_max_length = VLAN._meta.get_field("name").max_length


class IPFabricDiffSync(DiffSyncModelAdapters):
"""Nautobot adapter for DiffSync."""
Expand All @@ -31,7 +35,7 @@ def __init__(self, job, sync, client, *args, **kwargs):

def load_sites(self):
"""Add IP Fabric Site objects as DiffSync Location models."""
sites = self.client.get_sites()
sites = self.client.inventory.sites.all()
for site in sites:
try:
location = self.location(diffsync=self, name=site["siteName"], site_id=site["id"], status="Active")
Expand Down Expand Up @@ -76,19 +80,22 @@ def load_device_interfaces(self, device_model, interfaces, device_primary_ip):
def load(self):
"""Load data from IP Fabric."""
self.load_sites()
devices = self.client.get_device_inventory()
interfaces = self.client.get_interface_inventory()
vlans = self.client.get_vlans()
devices = self.client.inventory.devices.all()
interfaces = self.client.inventory.interfaces.all()
vlans = self.client.fetch_all("tables/vlan/site-summary")

for location in self.get_all(self.location):
if location.name is None:
continue
location_vlans = [vlan for vlan in vlans if vlan["siteName"] == location.name]
for vlan in location_vlans:
if not vlan["vlanId"]:
if not vlan["vlanId"] or (vlan["vlanId"] < 1 or vlan["vlanId"] > 4094):
self.job.log_warning(
message=f"Not syncing VLAN, NAME: {vlan.get('vlanName')} due to invalid VLAN ID: {vlan.get('vlanId')}."
)
continue
description = vlan.get("dscr") if vlan.get("dscr") else f"VLAN ID: {vlan['vlanId']}"
vlan_name = vlan.get("vlanName") if vlan.get("vlanName") else f"{vlan['siteName']}:{vlan['vlanId']}"
name_max_length = VLAN._meta.get_field("name").max_length
if len(vlan_name) > name_max_length:
self.job.log_warning(
message=f"Not syncing VLAN, {vlan_name} due to character limit exceeding {name_max_length}."
Expand All @@ -111,14 +118,23 @@ def load(self):
location_devices = [device for device in devices if device["siteName"] == location.name]
for device in location_devices:
device_primary_ip = device["loginIp"]
sn_length = len(device["sn"])
serial_number = device["sn"] if sn_length < device_serial_max_length else ""
if not serial_number:
self.job.log_warning(
message=(
f"Serial Number will not be recorded for {device['hostname']} due to character limit. "
f"{sn_length} exceeds {device_serial_max_length}"
)
)
try:
device_model = self.device(
diffsync=self,
name=device["hostname"],
location_name=device["siteName"],
model=device.get("model") if device.get("model") else f"Default-{device.get('vendor')}",
vendor=device.get("vendor").capitalize(),
serial_number=device["sn"],
serial_number=serial_number,
role=DEFAULT_DEVICE_ROLE,
status=DEFAULT_DEVICE_STATUS,
)
Expand Down
3 changes: 2 additions & 1 deletion nautobot_ssot_ipfabric/diffsync/diffsync_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Ignore return statements for updates and deletes, # pylint:disable=R1710
# Ignore too many args # pylint:disable=too-many-locals
"""DiffSyncModel subclasses for Nautobot-to-IPFabric data sync."""
from typing import Any, List, Optional, ClassVar
from typing import Any, ClassVar, List, Optional
from uuid import UUID

from diffsync import DiffSyncModel
from django.conf import settings
from django.core.exceptions import ValidationError
Expand Down
19 changes: 14 additions & 5 deletions nautobot_ssot_ipfabric/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
from django.conf import settings
from django.templatetags.static import static
from django.urls import reverse
from ipfabric import IPFClient
from nautobot.dcim.models import Site
from nautobot.extras.jobs import BooleanVar, Job, ScriptVariable
from nautobot.utilities.forms import DynamicModelChoiceField
from nautobot_ssot.jobs.base import DataMapping, DataSource

from nautobot_ssot_ipfabric.diffsync.diffsync_models import DiffSyncExtras

from nautobot_ssot_ipfabric.diffsync.adapter_ipfabric import IPFabricDiffSync
from nautobot_ssot_ipfabric.diffsync.adapter_nautobot import NautobotDiffSync
from nautobot_ssot_ipfabric.diffsync.adapters_shared import DiffSyncModelAdapters
from nautobot_ssot_ipfabric.utilities.ipfabric_client import IpFabricClient
from nautobot_ssot_ipfabric.diffsync.diffsync_models import DiffSyncExtras

CONFIG = settings.PLUGINS_CONFIG.get("nautobot_ssot_ipfabric", {})
IPFABRIC_HOST = CONFIG["ipfabric_host"]
IPFABRIC_API_TOKEN = CONFIG["ipfabric_api_token"]
IPFABRIC_SSL_VERIFY = CONFIG["ipfabric_ssl_verify"]
IPFABRIC_TIMEOUT = CONFIG["ipfabric_timeout"]


name = "SSoT - IPFabric" # pylint: disable=invalid-name

Expand Down Expand Up @@ -129,10 +131,17 @@ def log_debug(self, message):
if self.kwargs.get("debug"):
super().log_debug(message)

def load_source_adapter(self):
"""Not used."""

def load_target_adapter(self):
"""Not used."""

def sync_data(self):
"""Sync a device data from IP Fabric into Nautobot."""
client = IpFabricClient(IPFABRIC_HOST, IPFABRIC_API_TOKEN)

client = IPFClient(
IPFABRIC_HOST, token=IPFABRIC_API_TOKEN, verify=IPFABRIC_SSL_VERIFY, timeout=IPFABRIC_TIMEOUT
)
dry_run = self.kwargs["dry_run"]
safe_mode = self.kwargs["safe_delete_mode"]
tagged_only = self.kwargs["sync_ipfabric_tagged_only"]
Expand Down
111 changes: 0 additions & 111 deletions nautobot_ssot_ipfabric/tests/test_client.py

This file was deleted.

Loading

0 comments on commit d4eaa3b

Please sign in to comment.