### Python: Using Contributed Extensions in Design Builder Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Illustrates how to incorporate pre-built extensions from `nautobot_design_builder.contrib.ext` into a Design Job. This example specifically shows how to include the `BGPPeeringExtension`, which may require the BGP models plugin to be installed. ```python from nautobot_design_builder.design_builder import DesignJob from nautobot_design_builder.contrib import ext class DesignJobWithExtensions(DesignJob): class Meta: name = "Design with Custom Extensions" design_file = "templates/simple_design.yaml.j2" extensions = [ext.BGPPeeringExtension] ``` -------------------------------- ### Start Local Poetry Development Environment Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Installs dependencies with Nautobot extras, exports environment variables from development files, starts the Invoke environment, and applies database migrations for the local Poetry setup. ```shell poetry install --extras nautobot export $(cat development/development.env | xargs) export $(cat development/creds.env | xargs) invoke start && sleep 5 nautobot-server migrate ``` -------------------------------- ### Quick Start: VerifyDesignTestCase Setup in Python Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_job_testing.md Demonstrates how to set up `VerifyDesignTestCase` in a unittest file. It requires defining `job_design`, `check_file`, and `job_data` attributes, and calling `run_design_test` within a test method. The `check_file` uses the same check system as the Test Design framework. ```python class TestVerifyDesignJob(VerifyDesignTestCase): """Test running verify design jobs.""" job_design = test_designs.VerifyDesign check_file = os.path.join(os.path.dirname(__file__), "checks", "verify_design.yaml") job_data = {"additional_manufacturer_1": "Manufacturer From Data"} def test_my_design(self): self.run_design_test() ``` -------------------------------- ### Configure Nautobot App Plugins and Settings Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Demonstrates how to enable the nautobot_design_builder plugin and configure its settings within the `nautobot_config.py` file. This involves adding the plugin to the PLUGINS list and defining its configuration in PLUGINS_CONFIG. ```python # In your nautobot_config.py PLUGINS = ["nautobot_design_builder"] # PLUGINS_CONFIG = { # "nautobot_design_builder": { # ADD YOUR SETTINGS HERE # } # } ``` -------------------------------- ### Run Nautobot Post Upgrade Command Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Executes the `nautobot-server post_upgrade` command to apply database migrations and clear caches after configuration changes. This is a crucial step after modifying Nautobot's configuration or installing new plugins. ```shell nautobot-server post_upgrade ``` -------------------------------- ### Directory Structure for Designs Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Illustrates the recommended directory layout for organizing design components within a Nautobot app. It shows the placement of `__init__.py` files, context definitions (Python modules and YAML files), and Jinja2 design templates. ```bash jobs ├── __init__.py ├── core_site │   ├── __init__.py │   ├── context │   │   ├── __init__.py │   │   └── context.yaml │   └── designs │   └── 0001_design.yaml.j2 ├── edge_site │   ├── __init__.py │   ├── context │   │   ├── __init__.py │   │   └── context.yaml │   └── designs │   └── 0001_design.yaml.j2 └── initial_data ├── __init__.py ├── context │   ├── __init__.py └── designs └── 0001_design.yaml.j2 ``` -------------------------------- ### Install nautobot-design-builder using pip Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Installs the nautobot-design-builder package using pip, a Python package installer. This is the primary method for adding the app to your Nautobot environment. ```shell pip install nautobot-design-builder ``` -------------------------------- ### Install Nautobot Design Builder Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Instructions for installing the nautobot-design-builder Python package and ensuring its persistence across upgrades by adding it to local_requirements.txt. ```shell pip install nautobot-design-builder echo nautobot-design-builder >> local_requirements.txt ``` -------------------------------- ### Copy Credentials File for Nautobot Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Copies the example credentials file to a new file for local configuration. This file stores sensitive information like passwords and tokens for the Nautobot installation. It's a shell command. ```shell cp development/creds.example.env development/creds.env ``` -------------------------------- ### YAML Design Template with Update Action Tag Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Provides an example of using the '!update' action tag to modify an existing object. This template updates the description of an interface identified by its name. ```yaml - "!update:name": "Ethernet1/1" description: "new description for Ethernet1/1" ``` -------------------------------- ### Install Dependencies with Poetry Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Installs development dependencies using Poetry, including the poetry-plugin-shell for easier shell management. This is a prerequisite for running other development commands. ```shell poetry self add poetry-plugin-shell poetry shell poetry install ``` -------------------------------- ### Define Core Site Context Variables with Jinja Templating (YAML) Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md This YAML file defines two variables, `core_1_loopback` and `core_2_loopback`, for the design context. Their values are dynamically generated using Jinja2 templates, which leverage the `network_offset` filter from the `netutils` project to calculate IP addresses based on the `site_prefix` variable provided in the context. ```yaml --- core_1_loopback: "{{ site_prefix | network_offset('0.0.0.1/32') }}" core_2_loopback: "{{ site_prefix | network_offset('0.0.1.1/32') }}" ``` -------------------------------- ### Basic Design Job Implementation Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Demonstrates how to create a basic Design Job in Python for the Nautobot Design Builder. It shows inheriting from `DesignJob`, defining metadata like the design file, and registering the job using `register_jobs`. ```python from nautobot.apps.jobs import register_jobs from nautobot_design_builder.design_job import DesignJob class BasicDesign(DesignJob): """A basic design for design builder.""" class Meta: """Metadata describing this design job.""" name = "Basic Design" commit_default = False design_file = "designs/0001_design.yaml.j2" register_jobs(BasicDesign) ``` -------------------------------- ### Define CoreSiteContext with Validation and Dynamic Serial Number Generation (Python) Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md This Python code defines a `CoreSiteContext` class that extends `nautobot_design_builder.Context`. It includes instance variables for `region`, `site_name`, and `site_prefix`, and uses the `@context_file` decorator to load data from `context.yaml`. It also features a `validate_new_site` method for pre-implementation validation and a `get_serial_number` method demonstrating dynamic data retrieval. ```python from nautobot.dcim.models import Location from netaddr import IPNetwork from nautobot_design_builder.errors import DesignValidationError from nautobot_design_builder.context import Context, context_file @context_file("context.yaml") class CoreSiteContext(Context): """Render context for core site design""" region: Location site_name: str site_prefix: IPNetwork def validate_new_site(self): try: Location.objects.get(name__iexact=str(self.site_name)) raise DesignValidationError(f"Another site exist with the name {self.site_name}") except Location.DoesNotExist: return def get_serial_number(self, device_name): # ideally this would be an API call, or some external # process, to determine the serial number. This is just to # demonstrate var lookup from the context object return str(abs(hash(device_name))) ``` -------------------------------- ### Build and Start Docker Environment Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Builds the Docker images and starts the development environment services. This command assumes the Docker-based development environment is being used. ```shell invoke build invoke start ``` -------------------------------- ### Add nautobot-design-builder to local requirements Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Appends the nautobot-design-builder package name to the `local_requirements.txt` file. This ensures the package is re-installed during future Nautobot upgrades. ```shell echo nautobot-design-builder >> local_requirements.txt ``` -------------------------------- ### Git Context for Config Data - Jinja Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md The `!git_context` tag enables storing rendered configuration contexts directly into a Git repository. It requires `destination` and `data` keys. The `destination` specifies the file path within the repository, and `data` contains the content to be written. This feature requires the `context_repository` to be configured in `nautobot_config.py`. ```jinja "!git_context": destination: "config_contexts/devices/{{ device_name }}.yml" data: {% include 'templates/spine_switch_config_context.yaml.j2' %} ``` -------------------------------- ### Python: Defining a Design Job with Custom Extensions Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Shows how to define a custom extension for a Design Job in Python. The `extensions` attribute in the `Meta` class is used to register the custom extension class. This allows for custom action tags within the design templates. ```python from nautobot_design_builder.design_builder import DesignJob # Assuming CustomExtension is defined elsewhere # class CustomExtension(object): # pass class DesignJobWithExtensions(DesignJob): class Meta: name = "Design with Custom Extensions" design_file = "templates/simple_design.yaml.j2" extensions = [CustomExtension] ``` -------------------------------- ### Install Nautobot Plugin using Poetry Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Installs an additional Nautobot plugin, such as 'nautobot-chatops', using Poetry. This involves adding the plugin to the project's dependencies and rebuilding the Docker image to reflect the changes. ```bash # Install the plugin ➜ poetry add nautobot-chatops # Stop existing containers ➜ invoke stop # Rebuild the Docker image ➜ invoke build # Start containers ➜ invoke start ``` -------------------------------- ### YAML Design Template with Query Field (Dictionary) Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Illustrates using a query field with a dictionary value for more complex lookups. This allows specifying multiple criteria to find the correct related object, such as a platform with specific name and driver. ```yaml devices: - name: "switch1" platform: name: "Arista EOS" napalm_driver: "eos" ``` -------------------------------- ### Reference Object Lookup - Jinja Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md The `!ref:` syntax, when used as a value for a key, retrieves a previously stored object reference. This is commonly used in scenarios like cabling, where `termination_a` and `termination_b` can be assigned to previously created objects by looking up their reference names. ```jinja # Looking up a reference to previously created spine interfaces. # # In the rendered YAML "!ref:{{ spine.name }}:{{ interface }}" will become something like # "!ref:spine_switch1:Ethernet1", "!ref:spine_switch1:Ethernet2", etc # ObjectCreator will be able to assign the cable termination A side to the previously created objects. # # {% for leaf,interface in spine_to_leaf[loop.index0].items() %} - termination_a: "!ref:{{ spine.name }}:{{ interface }}" termination_b: "!ref:{{ leaf }}:{{ leaf_to_spine[leaf_index][spine_index] }}" status__name: "Planned" {% endfor %} ``` -------------------------------- ### Start Development Environment with Docker Compose Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Starts the Docker containers for the Nautobot development environment using Docker Compose. This command brings up services like Nautobot, its worker, PostgreSQL, Redis, and documentation server. It's an invoke command. ```bash ➜ invoke start Starting Nautobot in detached mode... Running docker-compose command "up --detach" Creating network "nautobot_design_builder_default" with the default driver Creating volume "nautobot_design_builder_postgres_data" with default driver Creating nautobot_design_builder_redis_1 ... Creating nautobot_design_builder_docs_1 ... Creating nautobot_design_builder_postgres_1 ... Creating nautobot_design_builder_postgres_1 ... done Creating nautobot_design_builder_redis_1 ... done Creating nautobot_design_builder_nautobot_1 ... Creating nautobot_design_builder_docs_1 ... done Creating nautobot_design_builder_nautobot_1 ... done Creating nautobot_design_builder_worker_1 ... Creating nautobot_design_builder_worker_1 ... done Docker Compose is now in the Docker CLI, try `docker compose up` ``` -------------------------------- ### Low-Level DesignTestCase Example in Python Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_job_testing.md An example of using `DesignTestCase` for lower-level testing of design jobs. This snippet shows how to mock a job, run it, assert the state of `Manufacturer` objects, and test for expected validation errors using `assertRaises`. ```python class TestDesignJob(DesignTestCase): """Test running design jobs.""" def test_simple_design_rollback(self): job1 = self.get_mocked_job(test_designs.SimpleDesign) job1.run(data={}, dryrun=False) self.assertEqual(2, Manufacturer.objects.all().count()) job2 = self.get_mocked_job(test_designs.SimpleDesign3) self.assertRaises(DesignValidationError, job2.run, data={}, dryrun=False) self.assertEqual(2, Manufacturer.objects.all().count()) ``` -------------------------------- ### Jinja Include Statement for Template Composition Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Demonstrates the Jinja {% include %} expression to insert content from another template file. The included file must maintain the same indentation level as the inclusion point to prevent YAML syntax errors. The path is relative to the design class definition. ```jinja --- devices: {% for device_name in device_names %} - name: "{{ device_name }}" {% include 'design_files/templates/switch_template.yaml.j2' %} {% endfor %} ``` -------------------------------- ### Run Nautobot Development Server Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/dev_environment.md Starts the Nautobot development server using the 'runserver' command. It's recommended to run this in a separate shell to manage the webserver independently. ```shell nautobot-server runserver 0.0.0.0:8080 --insecure ``` -------------------------------- ### Supplementary Context Values in YAML Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Example of a context.yaml file used to provide supplementary context values and Jinja2 templates for rendering. This includes calculated IP addresses and VLAN assignments. ```yaml # context.yaml - supplementary context values with Jinja2 templates --- core_1_loopback: "{{ site_prefix | network_offset('0.0.0.1/32') }}" core_2_loopback: "{{ site_prefix | network_offset('0.0.1.1/32') }}" management_vlan: 100 ``` -------------------------------- ### Define Core Backbone Site Design Job with Nautobot Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md This Python code defines a design job for creating a core backbone site. It inherits from DesignJob and uses Nautobot's `ObjectVar`, `StringVar`, and `IPNetworkVar` for user inputs like region, site name, and IP prefix. The `Meta` class specifies the design file and context class. ```python """Design to create a core backbone site.""" from nautobot.apps.jobs import register_jobs, ObjectVar, StringVar, IPNetworkVar from nautobot.dcim.models import Location from nautobot_design_builder.design_job import DesignJob from .context import CoreSiteContext class CoreSiteDesign(DesignJob): """Create a core backbone site.""" region = ObjectVar( label="Region", description="Region for the new backbone site", model=Location, ) site_name = StringVar(regex=r"\w{3}\d+") site_prefix = IPNetworkVar(min_prefix_length=16, max_prefix_length=22) has_sensitive_variables = False class Meta: """Metadata needed to implement the backbone site design.""" name = "Backbone Site Design" commit_default = False design_file = "designs/0001_design.yaml.j2" context_class = CoreSiteContext nautobot_version = ">=2" name = "Demo Designs" register_jobs(CoreSiteDesign) ``` -------------------------------- ### Check Device Existence (YAML) Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_testing.md This example demonstrates how to use the 'model_exists' check to verify if a specific device exists in Nautobot. It queries for a device with the name 'spine1' in the 'nautobot.dcim.models.Device' model. ```yaml checks: - model_exists: - model: "nautobot.dcim.models.Device" query: {name: "spine1"} ``` -------------------------------- ### Define CoreSiteContext Class Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Example of a custom Context class, CoreSiteContext, which extends the base Context class. It includes type hints for user inputs, a validation method (validate_new_site), and a custom method (get_serial_number) callable from templates. ```python from nautobot.dcim.models import Location from netaddr import IPNetwork from nautobot_design_builder.errors import DesignValidationError from nautobot_design_builder.context import Context, context_file @context_file("context.yaml") class CoreSiteContext(Context): """Render context for core site design.""" # Type hints for user-provided inputs region: Location site_name: str site_prefix: IPNetwork def validate_new_site(self): """Validation method - automatically called before implementation.""" try: Location.objects.get(name__iexact=str(self.site_name)) raise DesignValidationError(f"Site {self.site_name} already exists") except Location.DoesNotExist: return # Site doesn't exist, validation passes def get_serial_number(self, device_name): """Custom method callable from templates.""" # Could integrate with external CMDB API return str(abs(hash(device_name))) ``` -------------------------------- ### Verify Interface Connectivity Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_testing.md Checks if two network interfaces on different devices are connected by a cable. This example verifies connectivity between 'GigabitEthernet1' on 'Device 1' and 'GigabitEthernet1' on 'Device 2'. ```yaml checks: - connected: - model: "nautobot.dcim.models.Interface" query: {device__name: "Device 1", name: "GigabitEthernet1"} - model: "nautobot.dcim.models.Interface" query: {device__name: "Device 2", name: "GigabitEthernet1"} ``` -------------------------------- ### Bump Development Version with Poetry Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/release_checklist.md This sequence of commands updates the development version of the project using Poetry's 'prepatch' command. It then stages the 'pyproject.toml' file, commits the change, and pushes it to the repository. ```bash git switch main git pull git switch -c release-1.4.2-to-develop main poetry version prepatch git add pyproject.toml git commit -m "Bump version" git push ``` -------------------------------- ### Simplify Cable Provisioning with !connect_cable Extension Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Demonstrates the `!connect_cable` extension in Nautobot Design Builder, which simplifies cable creation by automatically handling termination lookups and cable provisioning directly within interface definitions. This reduces redundancy and streamlines the process of connecting network devices. ```yaml devices: - name: "device1" location__name: "Site-A" device_type__model: "test-type" role__name: "Router" status__name: "Active" "!ref": "device1" interfaces: - name: "GigabitEthernet1" type: "1000base-t" status__name: "Active" - name: "device2" location__name: "Site-A" device_type__model: "test-type" role__name: "Router" status__name: "Active" interfaces: - name: "GigabitEthernet1" type: "1000base-t" status__name: "Active" "!connect_cable": status__name: "Planned" type: "cat6" to: device: "!ref:device1" name: "GigabitEthernet1" ``` -------------------------------- ### Define Protected Data Models in Nautobot Config Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Configures data protection for specific models within Nautobot by specifying them in the `protected_models` list under `PLUGINS_CONFIG`. This example protects 'location' and 'device' models in the 'dcim' app. ```python PLUGINS_CONFIG = { "nautobot_design_builder": { "protected_models": [("dcim", "location"), ("dcim", "device")], ... } } ``` -------------------------------- ### Git Commands for Release Branching and Committing Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/release_checklist.md These commands demonstrate the process of creating a release branch, staging changes, committing them, and pushing to the remote repository. It includes updating the changelog and verifying staged files. ```bash git switch -c release-1.4.2 develop git add mkdocs.yml pyproject.toml git diff --cached git commit -m "Release v1.4.2" git push ``` -------------------------------- ### Generate Release Notes with Invoke Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/dev/release_checklist.md This command uses the 'invoke' tool to generate release notes. It can automatically detect the version from pyproject.toml or allow explicit version setting. Ensure the poetry environment is active. ```bash poetry install invoke generate-release-notes invoke generate-release-notes --version 1.4.2 ``` -------------------------------- ### Restart Nautobot Services Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Restarts the core Nautobot services, including the main application, worker, and scheduler. This ensures that all configuration changes are applied and the services are running correctly. ```shell sudo systemctl restart nautobot nautobot-worker nautobot-scheduler ``` -------------------------------- ### Enable Superuser Bypass for Data Protection Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Configures the nautobot_design_builder app to allow superusers to bypass data protection settings. This is achieved by setting `protected_superuser_bypass` to `False` in the `PLUGINS_CONFIG`. ```python PLUGINS_CONFIG = { "nautobot_design_builder": { "protected_superuser_bypass": False, ... } } ``` -------------------------------- ### Add Global Request Middleware for Data Protection Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/admin/install.md Inserts the `GlobalRequestMiddleware` from `nautobot_design_builder` into the Django `MIDDLEWARE` setting. This middleware is necessary for enabling features like superuser bypass of data protection. ```python MIDDLEWARE.insert(0, "nautobot_design_builder.middleware.GlobalRequestMiddleware") ``` -------------------------------- ### YAML Design Template with Nested Locations Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Demonstrates how to define hierarchical locations in a YAML design template. The Design Builder automatically handles the relationships between parent and child locations. ```yaml locations: - "name": "US-East-1" location_type__name: "Region" children: - "name": "IAD5" location_type__name: "Site" status__name: "Active" - "name": "LGA1" location_type__name: "Site" status__name: "Active" ``` -------------------------------- ### YAML Design Template with Query Field (Scalar) Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md Shows how to use a query field with a scalar value to associate a platform with a device. The Design Builder queries for a platform by its name and assigns it to the device. ```yaml devices: - name: "switch1" platform__name: "Arista EOS" ``` -------------------------------- ### Reference Object Creation - Jinja Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md The `!ref` tag, when used as a YAML mapping key, stores a reference to the current Nautobot object. This reference can be named and reused later in the design template, which is particularly useful for setting relationship fields, such as dynamically assigning uplink interfaces. ```jinja # Creating a reference to spine interfaces. # # In the rendered YAML this ends up being something like # "spine_switch1:Ethernet1", "spine_switch1:Ethernet2", etc # # - "!create_or_update:name": "{{ interface }}" "!ref": "{{ spine.name }}:{{ interface }}" ``` -------------------------------- ### Create Custom Attribute Extension in Python Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Demonstrates how to create a custom attribute extension by inheriting from `AttributeExtension`. This extension, `DeviceNamingExtension`, generates a standardized device name based on provided components like site code, role, and sequence. It includes error handling for incorrect input types and shows how to register the extension within a `DesignJob`. ```python from nautobot_design_builder.ext import AttributeExtension from nautobot_design_builder.design import Environment, ModelInstance from nautobot_design_builder.errors import DesignImplementationError class DeviceNamingExtension(AttributeExtension): """Custom extension for standardized device naming.""" tag = "standard_name" def attribute(self, *args, value=None, model_instance: ModelInstance = None): """Generate standardized device name from components. Args: *args: Additional colon-delimited arguments after tag name. value: Dictionary with naming components. model_instance: The device being created. Returns: Tuple of (attribute_name, computed_value). """ if not isinstance(value, dict): raise DesignImplementationError("standard_name requires a dictionary") site_code = value.get("site_code", "UNK") device_role = value.get("role", "device") sequence = value.get("sequence", 1) standard_name = f"{site_code}-{device_role}-{sequence:02d}" return "name", standard_name # Use in design template """ devices: - "!standard_name": site_code: "IAD5" role: "spine" sequence: 1 device_type__model: "Nexus 9336C" status__name: "Active" """ # Register extension in DesignJob class MyDesign(DesignJob): class Meta: name = "My Design" design_file = "designs/my_design.yaml.j2" extensions = [DeviceNamingExtension] ``` -------------------------------- ### Create or Update Object - YAML Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md The `!create_or_update` tag is used before a field name in YAML to either create a new object or update an existing one. If the object is not found, it will be created, but all required fields must be specified during creation. Design Builder validates models before saving to the database. ```yaml devices: - "!create_or_update:name": bb-rtr-1 "interfaces": - "!create_or_update:name": Ethernet1/1 description: "Uplink to provider" ``` -------------------------------- ### Define Initial Data Design Job with Nautobot Source: https://github.com/nautobot/nautobot-app-design-builder/blob/develop/docs/user/design_development.md This Python code defines an initial data design job that sets up default values for core site designs. It extends the DesignJob class and specifies metadata like the design file, context class, and user inputs for routers per site. It registers the job using `register_jobs`. ```python """Initial data required for core sites.""" from nautobot.apps.jobs import register_jobs, IntegerVar from nautobot_design_builder.design_job import DesignJob from .context import InitialDesignContext class InitialDesign(DesignJob): """Initialize the database with default values needed by the core site designs.""" has_sensitive_variables = False has_sensitive_variables = False routers_per_site = IntegerVar(min_value=1, max_value=6, default=2) class Meta: """Metadata needed to implement the backbone site design.""" name = "Initial Data" commit_default = False design_file = "designs/0001_design.yaml.j2" context_class = InitialDesignContext version = "1.0.0" description = "Establish the devices and site information for four sites: IAD5, LGA1, LAX11, SEA11." docs = """This design creates the following objects in the source of truth to establish the initia network environment in four sites: IAD5, LGA1, LAX11, SEA11. These sites belong to the America region (and different subregions), and use Juniper PTX10016 devices. The user input data is: - Number of routers per site (integer) - The description for us-west-1 region (string) """ name = "Demo Designs" register_jobs(InitialDesign) ``` -------------------------------- ### Manage Design Lifecycle with Nautobot Models in Python Source: https://context7.com/nautobot/nautobot-app-design-builder/llms.txt Illustrates how to manage the design lifecycle using Nautobot's ORM models. This snippet shows how to query `Design` and `Deployment` objects, iterate through deployments to access their status and associated `ChangeSet`s, and retrieve specific `Device` objects from a deployment. It highlights the capabilities for tracking changes and auditing modifications. ```python from nautobot_design_builder.models import Design, Deployment, ChangeSet, ChangeRecord from nautobot.dcim.models import Device # Query designs and deployments design = Design.objects.get(job__name="Backbone Site Design") print(f"Design: {design.name}, Version: {design.version}") # Get all deployments for a design for deployment in design.deployments.all(): print(f"Deployment: {deployment.name}") print(f" Status: {deployment.status}") print(f" First Implemented: {deployment.first_implemented}") print(f" Last Implemented: {deployment.last_implemented}") print(f" Created By: {deployment.created_by}") # Get all objects created/modified by this deployment for change_set in deployment.change_sets.filter(active=True): for record in change_set.records.all(): obj = record.design_object if obj: print(f" Object: {obj._meta.model_name} - {obj}") print(f" Full Control: {record.full_control}") print(f" Changes: {record.changes}") # Get specific model objects from a deployment deployment = Deployment.objects.get(name="IAD5-Core", design=design) devices = deployment.get_design_objects(Device) for device in devices: print(f"Device in deployment: {device.name}") ```