Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetBox 3.X #110

Merged
merged 54 commits into from
Jan 18, 2024
Merged

NetBox 3.X #110

merged 54 commits into from
Jan 18, 2024

Conversation

snaselj
Copy link
Contributor

@snaselj snaselj commented Nov 24, 2023

Closes: NaN

What's Changed

  • Dropped NetBox 2.x support.
  • Dropped ChangeLog import.
  • Implemented NetBox 3.0 - 3.6 support.
  • Dropped Nautobot 1.x support.
  • Implemented Nautobot 2.0 - 2.1 support.
  • Added importer development documentation.

Considerations

  • Implement writing created and last_updated fields.
  • Test to re-run the import.
  • Parametrize importer to fail if any validation fails.
  • Resolve skipped fields and TBDs in nautobot_netbox_importer/diffsync/netbox.py.
  • Resolve validation error: django.core.exceptions.ValidationError: ['Rack R308 (Row 3) and power panel Panel 4 (MDF) are in different locations'].
  • Resolve validation error: django.core.exceptions.ValidationError: {'parent': ['A Location of type Location may only have a Location of the same type as its parent.']}.
  • Change InternalTypeStr to enum.
  • Stream processing of input JSON file, to avoid loading the entire file into memory.

Not a scope of this PR

  • Implement mysql tests?
  • Implement SSoT Job.
    • Allow DiffSync deleting in Nautobot?
    • Add-only ManyToMany field values?
    • Add-only custom field values?

@glennmatthews
Copy link
Contributor

Was it necessary to move so much code around as part of this feature? I don't really know where to begin reviewing this when diff-wise it basically looks like an entirely new implementation of the app.

@glennmatthews
Copy link
Contributor

Also, does this just add 3.0 support or does it also drop support for all older NetBox versions? I can't really tell with the scope of the diffs here.

@snaselj
Copy link
Contributor Author

snaselj commented Dec 5, 2023

Was it necessary to move so much code around as part of this feature? I don't really know where to begin reviewing this when diff-wise it basically looks like an entirely new implementation of the app.

Yes, the implementation is different, supports multiple NetBox 3.0, 3.1 and 3.2 now, going to add support up to 3.6. Will prepare better developer documentation before making it ready for review.

@snaselj
Copy link
Contributor Author

snaselj commented Dec 5, 2023

Also, does this just add 3.0 support or does it also drop support for all older NetBox versions? I can't really tell with the scope of the diffs here.

Dropped support for Nautobot 1.x and NetBox 2.x, updated the description accordingly.

@snaselj snaselj marked this pull request as ready for review December 11, 2023 18:59
@glennmatthews
Copy link
Contributor

Just a quick note that changelog imports was a user-requested feature in the past. How difficult would it be to re-add?

@snaselj
Copy link
Contributor Author

snaselj commented Dec 11, 2023

Just a quick note that changelog imports was a user-requested feature in the past. How difficult would it be to re-add?

I don't have any testing data for it, so it's really difficult to estimate. Depends on the level of correctness, if it's just about importing JSON change object without change, then it should be quite easy to implement. When the importer should convert fields in JSON based on the content type, some issues can arise.

nautobot_netbox_importer/diffsync/base.py Outdated Show resolved Hide resolved
Comment on lines 6 to 16
from typing import Any
from typing import Iterable
from typing import List
from typing import Mapping
from typing import MutableMapping
from typing import Tuple
from typing import Type
from typing import Union
from uuid import NAMESPACE_DNS
from uuid import UUID
from uuid import uuid5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wouldn't the more usual black/isort/ruff convention be to group these, a la:

Suggested change
from typing import Any
from typing import Iterable
from typing import List
from typing import Mapping
from typing import MutableMapping
from typing import Tuple
from typing import Type
from typing import Union
from uuid import NAMESPACE_DNS
from uuid import UUID
from uuid import uuid5
from typing import (
Any,
Iterable,
List,
Mapping,
MutableMapping,
Tuple,
Type,
Union,
)
from uuid import NAMESPACE_DNS, UUID, uuid5

Same question/comment throughout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way passes through all CI checks and produces better git diffs.

nautobot_netbox_importer/diffsync/nautobot.py Outdated Show resolved Hide resolved
nautobot_netbox_importer/diffsync/nautobot.py Outdated Show resolved Hide resolved
Comment on lines 182 to 184
def set_instance_defaults(self, **defaults: Any) -> None:
"""Set default values for a Nautobot instance constructor."""
self.constructor_kwargs = defaults
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense for this to be set at __init__ time, or does it need to be a separate setter like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structure of wrappers is created on the fly. Some parts can be set in the constructors, however it's possible, that the wrapper will already exists, before configuring it.

nautobot_netbox_importer/diffsync/nautobot.py Outdated Show resolved Hide resolved
nautobot_netbox_importer/diffsync/nautobot.py Outdated Show resolved Hide resolved
nautobot_netbox_importer/diffsync/nautobot.py Outdated Show resolved Hide resolved
nautobot_netbox_importer/diffsync/netbox.py Outdated Show resolved Hide resolved
nautobot_netbox_importer/diffsync/source.py Outdated Show resolved Hide resolved
@chadell
Copy link
Contributor

chadell commented Dec 13, 2023

Overall feedback from notes:

  • Dropped NetBox 2.x support. -> Then, we should release a netbox-import version that supports as much as we did previous to this PR, and add a compatibility matrix
  • Dropped ChangeLog import. -> We should add this back, as @glennmatthews said, it was a customer ask and I see value for adopters.
  • Implemented NetBox 3.0 - 3.4 support.
  • Dropped Nautobot 1.x support. -> The same as point 1, we should have a release of NetBox 2.x -> Nautobot 1.x
  • Implemented Nautobot 2.0 support.

- Content Types Back Mapping: --------------------------------------------------
Back mapping deviations from Nautobot content type to the source content type
extras.role => Ambiguous
users.user => auth.user
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this in this list if not "Ambiguous"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list contain all deviations, mapping to the different content type is considered a deviation.


## Content Types Back Mapping

This section shows back mapping deviations from Nautobot content types to NetBox content types. Only those content types that differ between NetBox and Nautobot are shown.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the action task for the user with this info?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action is necessary from the user, just summarizing deviations to be aware of that.

_name (DATA) => _name (PrivateProperty)
label (DATA) => label (CharField)
description (DATA) => description (CharField)
module (DATA) => module (NotFound)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does it mean? is this information lost?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- `(ReadOnlyProperty')` marks fields that are read-only properties in Nautobot and can't be imported.
- `(PrivateProperty)` marks fields that are prefixed with an underscore `_` and are considered private properties. Those fields are not imported.
- `(NotFound)` indicates the field is not found in Nautobot and can't be imported.
- `(DoNotImportLastUpdated)` are fields that are not imported as they are automatically updated by Nautobot.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the word seems only for "LastUpdated" not for any field updated by Nautobot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the documentation to address this.

- `=>` as a separator.
- Nautobot field name.
- Field type in parentheses with the following special cases:
- `SKIPPED` means the field is intentionally skipped by the importer.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? could this be changed by the user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the importer to display disable reason, instead of SKIPPED for each disabled field.


The NetBox specific component is further segmented into sections, located in the `nautobot_netbox_importer/diffsync` directory:

- `adapters/nautobot.py`: Inherits `NautobotAdapter` from the generic `NautobotAdapter` and implements pieces necessary for SSoT job.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need a generic NautobotAdapter to create yet another NautobotAdapter? what is this abstraction providing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first one is DiffSync only related implementation. The other one is adding SSoT related things, but it's not probably necessary.

The reason to create the second one was to make the file structure the same way as is in other SSoT apps / integrations.


The initial step involves creating a `SourceAdapter()`. It accepts an argument, `get_source_data`, which is `Callable` that returns `Iterable` of the source data items. Each source data item is encapsulated in `SourceRecord(content_type: ContentTypeStr, data: Dict)` instances. `SourceAdapter` constructor also passes any additional arguments to its ancestor, the `DiffSync` class.

The data undergoes two cycles: the first to establish the structure and the second to import the actual data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you provide a structure with these two cycles and the sub steps involved?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Steps are described in this document, updated this doc to mention that.

@chadell
Copy link
Contributor

chadell commented Jan 10, 2024

General Questions:

  • What has to be done (as a developer) to support a Nautobot minor version?
  • What has to be done (as a developer) to support a Nautobot major version?
  • What has to be done (as a developer) to support a Nautobot App?
  • What has to be done (as a developer) to support a NetBox new version?
  • What has to be done (as a user) to provide some customization in the import method?

@bryanculver
Copy link
Member

General Questions:

  • What has to be done (as a developer) to support a Nautobot minor version?
  • What has to be done (as a developer) to support a Nautobot major version?
  • What has to be done (as a developer) to support a Nautobot App?
  • What has to be done (as a developer) to support a NetBox new version?
  • What has to be done (as a user) to provide some customization in the import method?

I'd suggest more targeted questions & answers, because if nothing changed between versions it can be a noop (AFAIK the way this refactor works is that it's data-type check instead of version check alleviates many of those concerns). So:

  • What has to be done (as a developer) if NetBox changes a field's data type?
  • (same as above but Nautobot side)
  • What has to be done (as a developer) if NetBox adds a new model?
  • What has to be done (as a developer) if NetBox changes a relation from 1-to-many to many-to-many?

Link to places where we are already handling these changes instead of speaking in hypotheticals.

I'd also like to see two other pieces of information:

  • A logical (not technical) diagram for the data from in from NetBox and out to Nautobot
    • [NetBox] -> SourceAdapter -> (what does data look like here and where it is "held") -> TargetAdapter -> [Nautobot]
    • And what types of decision trees does a data type transformation look like?
  • A few examples of roadblocks we ran into with the existing architecture when adding support for new versions (the below are hypotheticals so they are likely incorrect, but for demonstrations for justification)
    • "When adding support for Netbox 3.X+1 we were copying and pasting much of the same code for 3.X"
    • "When adding support for Nautobot 2.0, copy and paste code for Netbox 3.2-3.6 had to have repetitive updates and we found bugs where it was fixed in one place and not others"
    • "Removing support for Nautobot 1.X was proving to be very difficult and was effectively a rewrite anyway"

@snaselj snaselj changed the title NetBox 3.0 NetBox 3.X Jan 10, 2024
@snaselj
Copy link
Contributor Author

snaselj commented Jan 12, 2024

General Questions:

  • What has to be done (as a developer) to support a Nautobot minor version?
  • What has to be done (as a developer) to support a Nautobot major version?
  • What has to be done (as a developer) to support a Nautobot App?
  • What has to be done (as a developer) to support a NetBox new version?
  • What has to be done (as a user) to provide some customization in the import method?

I'd suggest more targeted questions & answers, because if nothing changed between versions it can be a noop (AFAIK the way this refactor works is that it's data-type check instead of version check alleviates many of those concerns). So:

  • What has to be done (as a developer) if NetBox changes a field's data type?
  • (same as above but Nautobot side)
  • What has to be done (as a developer) if NetBox adds a new model?
  • What has to be done (as a developer) if NetBox changes a relation from 1-to-many to many-to-many?

Link to places where we are already handling these changes instead of speaking in hypotheticals.

I'd also like to see two other pieces of information:

  • A logical (not technical) diagram for the data from in from NetBox and out to Nautobot

Still WIP

  • [NetBox] -> SourceAdapter -> (what does data look like here and where it is "held") -> TargetAdapter -> [Nautobot]

  • And what types of decision trees does a data type transformation look like?

  • A few examples of roadblocks we ran into with the existing architecture when adding support for new versions (the below are hypotheticals so they are likely incorrect, but for demonstrations for justification)

    • "When adding support for Netbox 3.X+1 we were copying and pasting much of the same code for 3.X"
    • "When adding support for Nautobot 2.0, copy and paste code for Netbox 3.2-3.6 had to have repetitive updates and we found bugs where it was fixed in one place and not others"
    • "Removing support for Nautobot 1.X was proving to be very difficult and was effectively a rewrite anyway"

Questions are addressed in doc/dev/faq.md and doc/user/faq.md.

@snaselj
Copy link
Contributor Author

snaselj commented Jan 12, 2024

General Questions:

  • What has to be done (as a developer) to support a Nautobot minor version?
  • What has to be done (as a developer) to support a Nautobot major version?
  • What has to be done (as a developer) to support a Nautobot App?
  • What has to be done (as a developer) to support a NetBox new version?
  • What has to be done (as a user) to provide some customization in the import method?

Questions are addressed in doc/dev/faq.md and doc/user/faq.md.

Comment on lines +82 to +88
## What has to be done to support a major NetBox version?

A new major version of the `nautobot-netbox-importer` package should be released to address updated deviations between NetBox and Nautobot models, independent of the previous major version.

## What has to be done to support a major Nautobot version?

Similar to the previous question, a new independent release of the `nautobot-netbox-importer` package should be released.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so every time a new major version for Nautobot or NetBox is released, a new major version of this app has to be released to match it. I guess this will be documented in a versions matrix or similar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be the best option for me. Optionally it would be possible to support multiple major NetBox releases at once. Depends on the release cadence, and the decision which major release matrix should be supported. This can be reconsidered in the future.

Updated compatibility matrix to cover the current status.


Similar to the previous question, a new independent release of the `nautobot-netbox-importer` package should be released.

## What has to be done to support a Nautobot App?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we planning to add out-of-the-box support to some Nautobot Apps? or it's only for customization?
if so, what happens when there is a new major release on a Nautobot App?

I understand that the NetBox plugin ecosystem could be also covered by this plugin with similar type of customization, isn't it? if so, maybe document it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, official Nautobot Apps support is a planned feature.

Added Q&A covering Nautobot / NetBox apps support.

@snaselj
Copy link
Contributor Author

snaselj commented Jan 16, 2024

  • A logical (not technical) diagram for the data from in from NetBox and out to Nautobot

Data flow diagram is here: https://github.com/nautobot/nautobot-app-netbox-importer/pull/110/files#diff-a854f6366a0abe3dea5e2e1ce1802a7123a271bb6670d891c805b923b7cfc77c

@snaselj
Copy link
Contributor Author

snaselj commented Jan 16, 2024

All comments should be addressed now.

wireless.wirelesslan => wireless.wirelesslan | Disabled with reason: Nautobot content type: `wireless.wirelesslan` not found
wireless.wirelesslink => wireless.wirelesslink | Disabled with reason: Nautobot content type: `wireless.wirelesslink` not found
django_rq.queue => django_rq.queue | Disabled with reason: Nautobot content type: `django_rq.queue` not found
secrets.secret => secrets.secret | Disabled with reason: Nautobot content type: `secrets.secret` not found
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as extras.secret?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to the follow-up ticket.

@bryanculver
Copy link
Member

I don't pretend to be the one who should be a gatekeeper to this PR, and I'm sure it might take some time to grok the documentation @snaselj has added but I do feel it should be re-reviewed.

Copy link
Contributor

@chadell chadell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Let's get this in, and it could be a great opportunity to create a follow-up PR to address the new NetBox 3.7 release to demonstrate how a new version should be added

@whitej6 whitej6 merged commit bca6058 into develop Jan 18, 2024
14 checks passed
@snaselj snaselj deleted the u/snaselj-netbox3 branch January 22, 2024 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants