nautobot / nautobot-app-ssot

Single Source of Truth for Nautobot
https://docs.nautobot.com/projects/ssot/en/latest/
Other
34 stars 30 forks source link

role__name returns None using contrib #370

Open rifen opened 4 months ago

rifen commented 4 months ago

Environment

Related Slack: https://networktocode.slack.com/archives/C01NWPK6WHL/p1708560079971619

Expected Behavior

Utilize role__name in my model that lets me add a role to my IPAddresses

Observed Behavior

The role would always return None using a created role or a default role like "Loopback"

Steps to Reproduce

  1. Add role__name to my attributes/data-types of my model using contrib
  2. Using the model with self.ipaddress (from nautobot.ipam.models import IPAddress) in this case. Added role__name="Loopback" for example.
  3. Run my SSOT job and I get back my dict but role is always None
Kircheneer commented 4 months ago

Thanks for submitting! Can you provide a full model and adapter to reference?

rifen commented 4 months ago

I believe this highlights what you are looking for (I didn't 1:1 copy and paste):

class IPAddressModel(NautobotModel):
    # Metadata about this model
    _model = IPAddress
    _modelname = "ipaddress"
    _identifiers = ("host",)
    _attributes = (
        "mask_length",
        "status__name",
        "role__name",
        "dns_name",
        "description",
        "parent__network",
    )

    # Data type declarations for all identifiers and attributes
    host: str
    mask_length: int
    status__name: str
    role__name: str
    dns_name: str
    description: Optional[str]
    parent__network: str

class NBAdapter(NautobotAdapter):
    ipaddress = IPAddressModel

    top_level = ["ipaddress"]

class Adapter(DiffSync):
    ipaddress = IPAddressModel

    top_level = ["ipaddress"]

    def __init__(self, job: object, sync: object, client: object, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.job = job
        self.client = client
        self.sync = sync

    def load(self):

      ip_data = [{
        "host": "10.1.1.2",
        "mask_length": "32",
        "status__name": "Reserved",
        "dns_name": "john.com",
        "description": "Jon Doe",
        "parent__network": "10.1.1.0",
        "role__name": "Loopback", # What it doesn't like
      }]

      for data in ip_data:
        ip_addr = self.ipaddress(
            host=data.get("host"),
            mask_length=data.get("mask_length"),
            status__name=data.get("status__name"),
            dns_name=data.get("dns_name"),
            description=data.get("description"),
            parent__network=data.get("parent__network"),
            role__name=data.get("role__name"), # What it doesn't like
        )
        self.add(ip_addr)
Kircheneer commented 4 months ago

If you can give me something I can run as is then I can reproduce the issue much quicker, i.e. flesh out

# GETS IP DATA AND ASSIGNS TO VARIABLES

with a list of dictionaries or something like this, and then include the actual operation that shows the faulty behaviour.

Thanks!

rifen commented 4 months ago

@Kircheneer I updated my comment from before. Let me know if this is sufficient.

Kircheneer commented 4 months ago

This looks good, thanks.