diff --git a/.devcontainer/Dockerfile-plugin_dev b/.devcontainer/Dockerfile-plugin_dev index 55fd2cb..ea10664 100644 --- a/.devcontainer/Dockerfile-plugin_dev +++ b/.devcontainer/Dockerfile-plugin_dev @@ -1,8 +1,8 @@ -ARG NETBOX_VARIANT=v3.3 +ARG NETBOX_VARIANT=v3.4 FROM netboxcommunity/netbox:${NETBOX_VARIANT} -ARG NETBOX_INITIALIZERS_VARIANT=3.3.* +ARG NETBOX_INITIALIZERS_VARIANT=3.4.* ARG DEBIAN_FRONTEND=noninteractive diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index a213cbe..b008240 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -10,37 +10,53 @@ services: #- netbox-worker env_file: env/netbox.env user: 'unit:root' + healthcheck: + start_period: 60s + timeout: 3s + interval: 15s + test: "curl -f http://localhost:8080/api/ || exit 1" volumes: - - ./initializers:/opt/netbox/initializers:z,ro - ./configuration:/etc/netbox/config:z,ro + #- ./reports:/etc/netbox/reports:z,ro + #- ./scripts:/etc/netbox/scripts:z,ro #- netbox-media-files:/opt/netbox/netbox/media:z #netbox-worker: # <<: *netbox # depends_on: - # - redis - # - postgres + # netbox: + # condition: service_healthy # command: # - /opt/netbox/venv/bin/python # - /opt/netbox/netbox/manage.py # - rqworker + # healthcheck: + # start_period: 20s + # timeout: 3s + # interval: 15s + # test: "ps -aux | grep -v grep | grep -q rqworker || exit 1" #netbox-housekeeping: # <<: *netbox # depends_on: - # - redis - # - postgres + # netbox: + # condition: service_healthy # command: # - /opt/netbox/housekeeping.sh + # healthcheck: + # start_period: 20s + # timeout: 3s + # interval: 15s + # test: "ps -aux | grep -v grep | grep -q housekeeping || exit 1" # postgres postgres: - image: postgres:14-alpine + image: postgres:15-alpine env_file: env/postgres.env volumes: - netbox-postgres-data:/var/lib/postgresql/data # redis redis: - image: redis:6-alpine + image: redis:7-alpine command: - sh - -c # this is to evaluate the $REDIS_PASSWORD from the env @@ -49,12 +65,14 @@ services: #volumes: # - netbox-redis-data:/data #redis-cache: - # image: redis:6-alpine + # image: redis:7-alpine # command: - # - sh - # - -c # this is to evaluate the $REDIS_PASSWORD from the env - # - redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose + # - sh + # - -c # this is to evaluate the $REDIS_PASSWORD from the env + # - redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose # env_file: env/redis-cache.env + # volumes: + # - netbox-redis-cache-data:/data volumes: #netbox-media-files: @@ -63,3 +81,5 @@ volumes: driver: local #netbox-redis-data: # driver: local + #netbox-redis-cache-data: + # driver: local diff --git a/.devcontainer/initializers/aggregates.yml b/.devcontainer/initializers/aggregates.yml deleted file mode 100644 index d41539d..0000000 --- a/.devcontainer/initializers/aggregates.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- prefix: 10.0.0.0/16 - rir: RFC1918 - tenant: tenant1 -- prefix: fd00:ccdd::/32 - rir: RFC4193 ULA -- prefix: 2001:db8::/32 - rir: RFC3849 diff --git a/.devcontainer/initializers/asns.yml b/.devcontainer/initializers/asns.yml deleted file mode 100644 index b65197c..0000000 --- a/.devcontainer/initializers/asns.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- asn: 1 - rir: RFC1918 - tenant: tenant1 -- asn: 2 - rir: RFC4193 ULA -- asn: 3 - rir: RFC3849 diff --git a/.devcontainer/initializers/cables.yml b/.devcontainer/initializers/cables.yml deleted file mode 100644 index 0e9b83d..0000000 --- a/.devcontainer/initializers/cables.yml +++ /dev/null @@ -1,72 +0,0 @@ ---- -# Required parameters for termination X ('a' or 'b'): -# -# ``` -# termination_x_name -> name of interface -# termination_x_device -> name of the device interface belongs to -# termination_x_class -> required if different from 'Interface' which is the default -# ``` -# -# Supported termination classes: Interface, ConsolePort, ConsoleServerPort, FrontPort, RearPort, PowerPort, PowerOutlet -# -# -# If a termination is a circuit then the required parameter is termination_x_circuit. -# Required parameters for a circuit termination: -# -# ``` -# termination_x_circuit: -# term_side -> termination side of a circuit. Must be A or B -# cid -> circuit ID value -# site OR provider_network -> name of Site or ProviderNetwork respectively. If both provided, Site takes precedence -# ``` -# -# If a termination is a power feed then the required parameter is termination_x_feed. -# -# ``` -# termination_x_feed: -# name -> name of the PowerFeed object -# power_panel: -# name -> name of the PowerPanel the PowerFeed is attached to -# site -> name of the Site in which the PowerPanel is present -# ``` -# -# Any other Cable parameters supported by Netbox are supported as the top level keys, e.g. 'type', 'status', etc. -# -# - termination_a_name: console -# termination_a_device: spine -# termination_a_class: ConsolePort -# termination_b_name: tty9 -# termination_b_device: console-server -# termination_b_class: ConsoleServerPort -# type: cat6 -# -- termination_a_name: to-server02 - termination_a_device: server01 - termination_b_name: to-server01 - termination_b_device: server02 - status: planned - type: mmf - -- termination_a_name: eth0 - termination_a_device: server02 - termination_b_circuit: - term_side: A - cid: Circuit_ID-1 - site: AMS 1 - type: cat6 - -- termination_a_name: psu0 - termination_a_device: server04 - termination_a_class: PowerPort - termination_b_feed: - name: power feed 1 - power_panel: - name: power panel AMS 1 - site: AMS 1 - -- termination_a_name: outlet1 - termination_a_device: server04 - termination_a_class: PowerOutlet - termination_b_name: psu1 - termination_b_device: server04 - termination_b_class: PowerPort diff --git a/.devcontainer/initializers/circuit_types.yml b/.devcontainer/initializers/circuit_types.yml deleted file mode 100644 index 5bd53e4..0000000 --- a/.devcontainer/initializers/circuit_types.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: VPLS - slug: vpls -- name: MPLS - slug: mpls -- name: Internet - slug: internet diff --git a/.devcontainer/initializers/circuits.yml b/.devcontainer/initializers/circuits.yml deleted file mode 100644 index b69efb3..0000000 --- a/.devcontainer/initializers/circuits.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- cid: Circuit_ID-1 - provider: Provider1 - type: Internet - tenant: tenant1 -- cid: Circuit_ID-2 - provider: Provider2 - type: MPLS diff --git a/.devcontainer/initializers/cluster_groups.yml b/.devcontainer/initializers/cluster_groups.yml deleted file mode 100644 index 503fd7e..0000000 --- a/.devcontainer/initializers/cluster_groups.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Group 1 - slug: group-1 -- name: Group 2 - slug: group-2 diff --git a/.devcontainer/initializers/cluster_types.yml b/.devcontainer/initializers/cluster_types.yml deleted file mode 100644 index c2342ac..0000000 --- a/.devcontainer/initializers/cluster_types.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -- name: Hyper-V - slug: hyper-v diff --git a/.devcontainer/initializers/clusters.yml b/.devcontainer/initializers/clusters.yml deleted file mode 100644 index c47ca5f..0000000 --- a/.devcontainer/initializers/clusters.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: cluster1 - type: Hyper-V - group: Group 1 - tenant: tenant1 -- name: cluster2 - type: Hyper-V - site: SING 1 diff --git a/.devcontainer/initializers/contact_groups.yml b/.devcontainer/initializers/contact_groups.yml deleted file mode 100644 index db171af..0000000 --- a/.devcontainer/initializers/contact_groups.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Network-Team - slug: network-team - description: This is a new contact group for the Network-Team -- name: New Contact Group - slug: new-contact-group - description: This is a new contact group sub under of Network-Team - parent: Network-Team diff --git a/.devcontainer/initializers/contact_roles.yml b/.devcontainer/initializers/contact_roles.yml deleted file mode 100644 index 858a225..0000000 --- a/.devcontainer/initializers/contact_roles.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: New Contact Role - slug: new-contact-role - description: This is a new contact role description diff --git a/.devcontainer/initializers/contacts.yml b/.devcontainer/initializers/contacts.yml deleted file mode 100644 index e48a81e..0000000 --- a/.devcontainer/initializers/contacts.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -- name: Lee Widget - title: CEO of Widget Corp - phone: 221-555-1212 - email: widgetCEO@widgetcorp.com - address: 1200 Nowhere Blvd, Scranton NJ, 555111 - comments: This is a very important contact -- name: Ali Gator - group: Network-Team - title: Consultant for Widget Corp - phone: 221-555-1213 - email: Consultant@widgetcorp.com - address: 1200 Nowhere Blvd, Scranton NJ, 555111 - comments: This is a very important contact -- name: Karlchen Maier - group: New Contact Group - title: COO of Widget Corp - phone: 221-555-1214 - email: Karlchen@widgetcorp.com - address: 1200 Nowhere Blvd, Scranton NJ, 555111 - comments: This is a very important contact diff --git a/.devcontainer/initializers/custom_fields.yml b/.devcontainer/initializers/custom_fields.yml deleted file mode 100644 index 0687a2b..0000000 --- a/.devcontainer/initializers/custom_fields.yml +++ /dev/null @@ -1,118 +0,0 @@ ---- -## Possible Choices: -## type: -## - text -## - integer -## - boolean -## - date -## - url -## - select -## - multiselect -## - object -## - multiobject -## filter_logic: -## - disabled -## - loose -## - exact -## -## Examples: - -text_field: - type: text - label: Custom Text - description: Enter text in a text field. - required: false - weight: 0 - on_objects: - - dcim.models.Device - - dcim.models.Rack - - dcim.models.Site - - dcim.models.DeviceType - - ipam.models.IPAddress - - ipam.models.Prefix - - tenancy.models.Tenant - - virtualization.models.VirtualMachine -integer_field: - type: integer - label: Custom Number - description: Enter numbers into an integer field. - required: true - filter_logic: loose - validation_minimum: 0 - validation_maximum: 255 - weight: 10 - on_objects: - - tenancy.models.Tenant -select_field: - type: select - label: Choose between items - required: false - filter_logic: exact - weight: 30 - default: First Item - on_objects: - - dcim.models.Device - choices: - - First Item - - Second Item - - Third Item - - Fifth Item - - Fourth Item -select_field_legacy_format: - type: select - label: Choose between items - required: false - filter_logic: loose - weight: 30 - on_objects: - - dcim.models.Device - choices: - - value: A # this is the deprecated format. - - value: B # we only use it for the tests. - - value: C # please see above for the new format. - - value: "D like deprecated" - weight: 999 - - value: E -boolean_field: - type: boolean - label: Yes Or No? - required: true - filter_logic: loose - default: "false" # important: put "false" in quotes! - weight: 90 - on_objects: - - dcim.models.Device -url_field: - type: url - label: Hyperlink - description: Link to something nice. - required: true - filter_logic: disabled - validation_regex: ^https:// - on_objects: - - tenancy.models.Tenant -date_field: - type: date - label: Important Date - required: false - filter_logic: disabled - on_objects: - - dcim.models.Device -multiobject_field: - type: multiobject - label: Related Objects - description: IP addresses that belong to this location - required: true - filter_logic: loose - on_objects: - - dcim.models.Location - object_type: ipam.models.IPAddress -object_field: - type: object - label: ASN - description: This device has an ASN now - required: false - filter_logic: loose - on_objects: - - dcim.models.Device - object_type: ipam.models.ASN diff --git a/.devcontainer/initializers/custom_links.yml b/.devcontainer/initializers/custom_links.yml deleted file mode 100644 index c7348bc..0000000 --- a/.devcontainer/initializers/custom_links.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -## Possible Choices: -## new_window: -## - True -## - False -## content_type: -## - device -## - site -## - any-other-content-type -## -## Examples: - -- name: link_to_repo - link_text: 'Link to Netbox Docker' - link_url: 'https://github.com/netbox-community/netbox-docker' - new_window: False - content_type: device -- name: link_to_localhost - link_text: 'Link to localhost' - link_url: 'http://localhost' - new_window: True - content_type: device diff --git a/.devcontainer/initializers/device_roles.yml b/.devcontainer/initializers/device_roles.yml deleted file mode 100644 index aa829c9..0000000 --- a/.devcontainer/initializers/device_roles.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -- name: switch - slug: switch - color: Grey -- name: router - slug: router - color: Cyan -- name: load-balancer - slug: load-balancer - color: Red -- name: server - slug: server - color: Blue -- name: patchpanel - slug: patchpanel - color: Black diff --git a/.devcontainer/initializers/device_types.yml b/.devcontainer/initializers/device_types.yml deleted file mode 100644 index 08c472f..0000000 --- a/.devcontainer/initializers/device_types.yml +++ /dev/null @@ -1,58 +0,0 @@ ---- -- model: Model 1 - manufacturer: Manufacturer 1 - slug: model-1 - u_height: 2 - custom_field_data: - text_field: Description -- model: Model 2 - manufacturer: Manufacturer 1 - slug: model-2 - custom_field_data: - text_field: Description -- model: Model 3 - manufacturer: Manufacturer 1 - slug: model-3 - is_full_depth: false - u_height: 0 - custom_field_data: - text_field: Description -- model: Other - manufacturer: No Name - slug: other - custom_field_data: - text_field: Description - interfaces: - - name: eth0 - type: 1000base-t - mgmt_only: True - - name: eth1 - type: 1000base-t - console_server_ports: - - name_template: ttyS[1-48] - type: rj-45 - power_ports: - - name_template: psu[0,1] - type: iec-60320-c14 - maximum_draw: 35 - allocated_draw: 35 - front_ports: - - name_template: front[1,2] - type: 8p8c - rear_port_template: rear[0,1] - rear_port_position_template: "[1,2]" - rear_ports: - - name_template: rear[0,1] - type: 8p8c - positions_template: "[3,2]" - device_bays: - - name: bay0 # both non-template and template field specified; non-template field takes precedence - name_template: bay[0-9] - label: test0 - label_template: test[0-5,9,6-8] - description: Test description - power_outlets: - - name_template: outlet[0,1] - type: iec-60320-c5 - power_port: psu0 - feed_leg: B diff --git a/.devcontainer/initializers/devices.yml b/.devcontainer/initializers/devices.yml deleted file mode 100644 index 06a0fbf..0000000 --- a/.devcontainer/initializers/devices.yml +++ /dev/null @@ -1,54 +0,0 @@ ---- -## Possible Choices: -## face: -## - front -## - rear -## status: -## - offline -## - active -## - planned -## - staged -## - failed -## - inventory -## - decommissioning -## -## Examples: - -- name: server01 - device_role: server - device_type: Other - site: AMS 1 - rack: rack-01 - face: front - position: 1 - custom_field_data: - text_field: Description -- name: server02 - device_role: server - device_type: Other - site: AMS 2 - rack: rack-02 - face: front - position: 2 - primary_ip4: 10.1.1.2/24 - primary_ip6: 2001:db8:a000:1::2/64 - custom_field_data: - text_field: Description -- name: server03 - device_role: server - device_type: Other - site: SING 1 - rack: rack-03 - face: front - position: 3 - custom_field_data: - text_field: Description -- name: server04 - device_role: server - device_type: Other - site: SING 1 - location: cage 101 - face: front - position: 3 - custom_field_data: - text_field: Description diff --git a/.devcontainer/initializers/groups.yml b/.devcontainer/initializers/groups.yml deleted file mode 100644 index c49242f..0000000 --- a/.devcontainer/initializers/groups.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -applications: - users: - - technical_user -readers: - users: - - reader -writers: - users: - - writer diff --git a/.devcontainer/initializers/interfaces.yml b/.devcontainer/initializers/interfaces.yml deleted file mode 100644 index f3c8309..0000000 --- a/.devcontainer/initializers/interfaces.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- -## Possible Choices: -## type: -## - virtual -## - lag -## - 1000base-t -## - ... and many more. See for yourself: -## https://github.com/netbox-community/netbox/blob/295d4f0394b431351c0cb2c3ecc791df68c6c2fb/netbox/dcim/choices.py#L510 -## -## Examples: - -- device: server01 - name: ath0 - type: 1000base-t - lag: ae0 - bridge: br0 -- device: server01 - name: ath1 - type: 1000base-t - parent: ath0 -- device: server01 - enabled: true - type: 1000base-x-sfp - name: to-server02 -- device: server02 - enabled: true - type: 1000base-x-sfp - name: to-server01 -- device: server02 - enabled: true - type: 1000base-t - name: eth0 -- device: server02 - enabled: true - type: virtual - name: loopback diff --git a/.devcontainer/initializers/ip_addresses.yml b/.devcontainer/initializers/ip_addresses.yml deleted file mode 100644 index a81cb3a..0000000 --- a/.devcontainer/initializers/ip_addresses.yml +++ /dev/null @@ -1,45 +0,0 @@ ---- -## Possible Choices: -## status: -## - active -## - reserved -## - deprecated -## - dhcp -## role: -## - loopback -## - secondary -## - anycast -## - vip -## - vrrp -## - hsrp -## - glbp -## - carp -## -## Examples: - -- address: 10.1.1.1/24 - device: server01 - interface: to-server02 - status: active - vrf: vrf1 -- address: 2001:db8:a000:1::1/64 - device: server01 - interface: to-server02 - status: active - vrf: vrf1 -- address: 10.1.1.2/24 - device: server02 - interface: to-server01 - status: active -- address: 2001:db8:a000:1::2/64 - device: server02 - interface: to-server01 - status: active -- address: 10.1.1.10/24 - description: reserved IP - status: reserved - tenant: tenant1 -- address: 2001:db8:a000:1::10/64 - description: reserved IP - status: reserved - tenant: tenant1 diff --git a/.devcontainer/initializers/locations.yml b/.devcontainer/initializers/locations.yml deleted file mode 100644 index 3595f7d..0000000 --- a/.devcontainer/initializers/locations.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: cage 101 - slug: cage-101 - site: SING 1 diff --git a/.devcontainer/initializers/manufacturers.yml b/.devcontainer/initializers/manufacturers.yml deleted file mode 100644 index 8463d76..0000000 --- a/.devcontainer/initializers/manufacturers.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Manufacturer 1 - slug: manufacturer-1 -- name: Manufacturer 2 - slug: manufacturer-2 -- name: No Name - slug: no-name diff --git a/.devcontainer/initializers/object_permissions.yml b/.devcontainer/initializers/object_permissions.yml deleted file mode 100644 index 4914bdc..0000000 --- a/.devcontainer/initializers/object_permissions.yml +++ /dev/null @@ -1,61 +0,0 @@ ---- -all.ro: - actions: - - view - description: 'Read Only for All Objects' - enabled: true - groups: - - applications - - readers - object_types: all - users: - - jdoe -all.rw: - actions: - - add - - change - - delete - - view - description: 'Read/Write for All Objects' - enabled: true - groups: - - writers - object_types: all -network_team.rw: - actions: - - add - - change - - delete - - view - description: "Network Team Permissions" - enabled: true - object_types: - circuits: - - circuit - - circuittermination - - circuittype - - provider - dcim: all - ipam: - - aggregate - - ipaddress - - prefix - - rir - - role - - routetarget - - service - - vlan - - vlangroup - - vrf -vips.change: - actions: - - change - description: "Update VIP object permission" - enabled: true - object_types: - ipam: - - ipaddress - groups: - - devops - constraints: - role: vip diff --git a/.devcontainer/initializers/platforms.yml b/.devcontainer/initializers/platforms.yml deleted file mode 100644 index 510ab04..0000000 --- a/.devcontainer/initializers/platforms.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -- name: Platform 1 - slug: platform-1 - manufacturer: Manufacturer 1 - napalm_driver: driver1 - napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}" -- name: Platform 2 - slug: platform-2 - manufacturer: Manufacturer 2 - napalm_driver: driver2 - napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}" -- name: Platform 3 - slug: platform-3 - manufacturer: No Name - napalm_driver: driver3 - napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}" diff --git a/.devcontainer/initializers/power_feeds.yml b/.devcontainer/initializers/power_feeds.yml deleted file mode 100644 index a32e3dd..0000000 --- a/.devcontainer/initializers/power_feeds.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -- name: power feed 1 - power_panel: power panel AMS 1 - voltage: 208 - amperage: 50 - max_utilization: 80 - phase: Single phase - rack: rack-01 -- name: power feed 2 - power_panel: power panel SING 1 - voltage: 208 - amperage: 50 - max_utilization: 80 - phase: Three-phase - rack: rack-03 diff --git a/.devcontainer/initializers/power_panels.yml b/.devcontainer/initializers/power_panels.yml deleted file mode 100644 index 757b4b3..0000000 --- a/.devcontainer/initializers/power_panels.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: power panel AMS 1 - site: AMS 1 -- name: power panel SING 1 - site: SING 1 - location: cage 101 diff --git a/.devcontainer/initializers/prefix_vlan_roles.yml b/.devcontainer/initializers/prefix_vlan_roles.yml deleted file mode 100644 index 4f269c7..0000000 --- a/.devcontainer/initializers/prefix_vlan_roles.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -- name: Main Management - slug: main-management diff --git a/.devcontainer/initializers/prefixes.yml b/.devcontainer/initializers/prefixes.yml deleted file mode 100644 index 78ae23c..0000000 --- a/.devcontainer/initializers/prefixes.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -## Possible Choices: -## status: -## - container -## - active -## - reserved -## - deprecated -## -## Examples: - -- description: prefix1 - prefix: 10.1.1.0/24 - site: AMS 1 - status: active - tenant: tenant1 - vlan: vlan1 -- description: prefix2 - prefix: 10.1.2.0/24 - site: AMS 2 - status: active - tenant: tenant2 - vlan: vlan2 - is_pool: true - vrf: vrf2 -- description: ipv6 prefix1 - prefix: 2001:db8:a000:1::/64 - site: AMS 2 - status: active - tenant: tenant2 - vlan: vlan2 diff --git a/.devcontainer/initializers/providers.yml b/.devcontainer/initializers/providers.yml deleted file mode 100644 index 6465b82..0000000 --- a/.devcontainer/initializers/providers.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -- name: Provider1 - slug: provider1 - asn: 121 -- name: Provider2 - slug: provider2 - asn: 122 diff --git a/.devcontainer/initializers/rack_roles.yml b/.devcontainer/initializers/rack_roles.yml deleted file mode 100644 index 54e95ed..0000000 --- a/.devcontainer/initializers/rack_roles.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Role 1 - slug: role-1 - color: Pink -- name: Role 2 - slug: role-2 - color: Cyan -- name: Role 3 - slug: role-3 - color: Grey -- name: Role 4 - slug: role-4 - color: Teal diff --git a/.devcontainer/initializers/racks.yml b/.devcontainer/initializers/racks.yml deleted file mode 100644 index 05d6b22..0000000 --- a/.devcontainer/initializers/racks.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -## Possible Choices: -## width: -## - 19 -## - 23 -## types: -## - 2-post-frame -## - 4-post-frame -## - 4-post-cabinet -## - wall-frame -## - wall-cabinet -## outer_unit: -## - mm -## - in -## -## Examples: - -- site: AMS 1 - name: rack-01 - role: Role 1 - type: 4-post-cabinet - width: 19 - u_height: 47 - custom_field_data: - text_field: Description -- site: AMS 2 - name: rack-02 - role: Role 2 - type: 4-post-cabinet - width: 19 - u_height: 47 - custom_field_data: - text_field: Description -- site: SING 1 - name: rack-03 - location: cage 101 - role: Role 3 - type: 4-post-cabinet - width: 19 - u_height: 47 - custom_field_data: - text_field: Description diff --git a/.devcontainer/initializers/regions.yml b/.devcontainer/initializers/regions.yml deleted file mode 100644 index a818c6f..0000000 --- a/.devcontainer/initializers/regions.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Singapore - slug: singapore -- name: Amsterdam - slug: amsterdam -- name: Downtown - slug: downtown - parent: Amsterdam -- name: Suburbs - slug: suburbs - parent: Amsterdam diff --git a/.devcontainer/initializers/rirs.yml b/.devcontainer/initializers/rirs.yml deleted file mode 100644 index 34777f9..0000000 --- a/.devcontainer/initializers/rirs.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- is_private: true - name: RFC1918 - slug: rfc1918 -- is_private: true - name: RFC4193 ULA - slug: rfc4193-ula -- is_private: true - name: RFC3849 - slug: rfc3849 diff --git a/.devcontainer/initializers/route_targets.yml b/.devcontainer/initializers/route_targets.yml deleted file mode 100644 index 2fa188e..0000000 --- a/.devcontainer/initializers/route_targets.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- name: 65000:1001 - tenant: tenant1 -- name: 65000:1002 diff --git a/.devcontainer/initializers/services.yml b/.devcontainer/initializers/services.yml deleted file mode 100644 index 88cd473..0000000 --- a/.devcontainer/initializers/services.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -- name: DNS - protocol: TCP - ports: - - 53 - virtual_machine: virtual machine 1 -- name: DNS - protocol: UDP - ports: - - 53 - virtual_machine: virtual machine 1 -- name: MISC - protocol: UDP - ports: - - 4000 - device: server01 diff --git a/.devcontainer/initializers/sites.yml b/.devcontainer/initializers/sites.yml deleted file mode 100644 index cbc20b8..0000000 --- a/.devcontainer/initializers/sites.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: AMS 1 - slug: ams1 - region: Downtown - status: active - facility: Amsterdam 1 - custom_field_data: - text_field: Description for AMS1 -- name: AMS 2 - slug: ams2 - region: Downtown - status: active - facility: Amsterdam 2 - custom_field_data: - text_field: Description for AMS2 -- name: AMS 3 - slug: ams3 - region: Suburbs - status: active - facility: Amsterdam 3 - tenant: tenant1 - custom_field_data: - text_field: Description for AMS3 -- name: SING 1 - slug: sing1 - region: Singapore - status: active - facility: Singapore 1 - tenant: tenant2 - custom_field_data: - text_field: Description for SING1 diff --git a/.devcontainer/initializers/tags.yml b/.devcontainer/initializers/tags.yml deleted file mode 100644 index 2697237..0000000 --- a/.devcontainer/initializers/tags.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- name: Tag 1 - slug: tag-1 - color: Pink -- name: Tag 2 - slug: tag-2 - color: Cyan -- name: Tag 3 - slug: tag-3 - color: Grey -- name: Tag 4 - slug: tag-4 - color: Teal diff --git a/.devcontainer/initializers/tenant_groups.yml b/.devcontainer/initializers/tenant_groups.yml deleted file mode 100644 index 79fa5cb..0000000 --- a/.devcontainer/initializers/tenant_groups.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Tenant Group 1 - slug: tenant-group-1 -- name: Tenant Group 2 - slug: tenant-group-2 diff --git a/.devcontainer/initializers/tenants.yml b/.devcontainer/initializers/tenants.yml deleted file mode 100644 index d3a983e..0000000 --- a/.devcontainer/initializers/tenants.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- name: tenant1 - slug: tenant1 -- name: tenant2 - slug: tenant2 - group: Tenant Group 2 diff --git a/.devcontainer/initializers/users.yml b/.devcontainer/initializers/users.yml deleted file mode 100644 index d6ebd18..0000000 --- a/.devcontainer/initializers/users.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -technical_user: - api_token: "" # a token is generated automatically unless the value is explicity set to empty -reader: - api_token: "" # a token is generated automatically unless the value is explicity set to empty -writer: - api_token: "" # a token is generated automatically unless the value is explicity set to empty -jdoe: - first_name: John - last_name: Doe - is_active: True - is_superuser: False - is_staff: False diff --git a/.devcontainer/initializers/virtual_machines.yml b/.devcontainer/initializers/virtual_machines.yml deleted file mode 100644 index bc2c4ee..0000000 --- a/.devcontainer/initializers/virtual_machines.yml +++ /dev/null @@ -1,29 +0,0 @@ ---- -## Possible Choices: -## status: -## - active -## - offline -## - staged -## -## Examples: - -- cluster: cluster1 - comments: VM1 - disk: 200 - memory: 4096 - name: virtual machine 1 - platform: Platform 2 - status: active - tenant: tenant1 - vcpus: 8 -- cluster: cluster1 - comments: VM2 - disk: 100 - memory: 2048 - name: virtual machine 2 - platform: Platform 2 - primary_ip4: 10.1.1.10/24 - primary_ip6: 2001:db8:a000:1::10/64 - status: active - tenant: tenant1 - vcpus: 8 diff --git a/.devcontainer/initializers/virtualization_interfaces.yml b/.devcontainer/initializers/virtualization_interfaces.yml deleted file mode 100644 index 396a8c8..0000000 --- a/.devcontainer/initializers/virtualization_interfaces.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -- description: Network Interface 1 - enabled: true - mac_address: 00:77:77:77:77:77 - mtu: 1500 - name: Network Interface 1 - virtual_machine: virtual machine 1 -- description: Network Interface 2 - enabled: true - mac_address: 00:55:55:55:55:55 - mtu: 1500 - name: Network Interface 2 - virtual_machine: virtual machine 1 diff --git a/.devcontainer/initializers/vlan_groups.yml b/.devcontainer/initializers/vlan_groups.yml deleted file mode 100644 index 6aae0d8..0000000 --- a/.devcontainer/initializers/vlan_groups.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -- name: VLAN group 1 - scope_type: dcim.region - scope: Amsterdam - slug: vlan-group-1 -- name: VLAN group 2 - scope_type: dcim.site - scope: AMS 1 - slug: vlan-group-2 -- name: VLAN group 3 - scope_type: dcim.location - scope: cage 101 - slug: vlan-group-3 -- name: VLAN group 4 - scope_type: dcim.rack - scope: rack-01 - slug: vlan-group-4 -- name: VLAN group 5 - scope_type: virtualization.cluster - scope: cluster1 - slug: vlan-group-5 -- name: VLAN group 6 - scope_type: virtualization.clustergroup - scope: Group 1 - slug: vlan-group-6 diff --git a/.devcontainer/initializers/vlans.yml b/.devcontainer/initializers/vlans.yml deleted file mode 100644 index d2c8543..0000000 --- a/.devcontainer/initializers/vlans.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -## Possible Choices: -## status: -## - active -## - reserved -## - deprecated -## -## Examples: - -- name: vlan1 - site: AMS 1 - status: active - vid: 5 - role: Main Management - description: VLAN 5 for MGMT -- group: VLAN group 2 - name: vlan2 - site: AMS 1 - status: active - vid: 1300 diff --git a/.devcontainer/initializers/vrfs.yml b/.devcontainer/initializers/vrfs.yml deleted file mode 100644 index accb990..0000000 --- a/.devcontainer/initializers/vrfs.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- enforce_unique: true - name: vrf1 - tenant: tenant1 - description: main VRF -- enforce_unique: true - name: vrf2 - rd: "6500:6500" - tenant: tenant2 diff --git a/.devcontainer/initializers/webhooks.yml b/.devcontainer/initializers/webhooks.yml deleted file mode 100644 index f25260c..0000000 --- a/.devcontainer/initializers/webhooks.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- -## Possible Choices: -## object_types: -## - device -## - site -## - any-other-content-type -## types: -## - type_create -## - type_update -## - type_delete -## Examples: - -- name: device_creation - payload_url: 'http://localhost:8080' - object_types: - - device - - cable - type_create: True -- name: device_update - payload_url: 'http://localhost:8080' - object_types: - - device - type_update: True -- name: device_delete - payload_url: 'http://localhost:8080' - object_types: - - device - type_delete: True diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index a88d335..ac362e9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -23,14 +23,14 @@ body: attributes: label: NetBox access-list plugin version description: What version of the NetBox access-list plugin are you currently running? - placeholder: v0.1 + placeholder: v1.2.0 validations: required: true - type: input attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.7 + placeholder: v3.4.3 validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index a388992..ca31eaf 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -15,7 +15,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.5 + placeholder: v3.4.3 validations: required: true - type: dropdown diff --git a/Makefile b/Makefile index 44e8234..aa6c2f9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ PLUGIN_NAME=netbox_acls REPO_PATH=/opt/netbox/netbox/netbox-acls VENV_PY_PATH=/opt/netbox/venv/bin/python3 -NETBOX_MANAGE_PATH=/opt/netbox/netbox/manage.py +NETBOX_MANAGE_PATH=/opt/netbox/netbox +NETBOX_INITIALIZER_PATH=${NETBOX_MANAGE_PATH}/netbox_initializers/ VERFILE=./version.py .PHONY: help ## Display help message @@ -26,7 +27,7 @@ help: .PHONY: nbshell ## Run nbshell nbshell: - ${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} nbshell + ${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py nbshell from netbox_acls.models import * .PHONY: setup ## Copy plugin settings. Setup NetBox plugin. @@ -36,27 +37,31 @@ setup: .PHONY: example_initializers ## Run initializers example_initializers: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} copy_initializers_examples --path /opt/netbox/netbox/netbox-acls/.devcontainer/initializers + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py copy_initializers_examples --path /opt/netbox/netbox/netbox-acls/.devcontainer/initializers .PHONY: load_initializers ## Run initializers load_initializers: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} load_initializer_data --path /opt/netbox/netbox/netbox-acls/.devcontainer/initializers + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py load_initializer_data --path /opt/netbox/netbox/netbox-acls/.devcontainer/initializers .PHONY: makemigrations ## Run makemigrations makemigrations: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} makemigrations --name ${PLUGIN_NAME} + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py makemigrations --name ${PLUGIN_NAME} .PHONY: migrate ## Run migrate migrate: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} migrate + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py migrate .PHONY: collectstatic collectstatic: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} collectstatic --no-input + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py collectstatic --no-input .PHONY: initializers initializers: - -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH} load_initializer_data --path /opt/netbox/netbox/netbox-acls/.devcontainer/initializers + -rm -rf ${NETBOX_INITIALIZER_PATH} + -mkdir ${NETBOX_INITIALIZER_PATH} + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py copy_initializers_examples --path ${NETBOX_INITIALIZER_PATH} + -for file in ${NETBOX_INITIALIZER_PATH}/*.yml; do sed -i "s/^# //g" "$$file"; done + -${VENV_PY_PATH} ${NETBOX_MANAGE_PATH}/manage.py load_initializer_data --path ${NETBOX_INITIALIZER_PATH} .PHONY: start ## Start NetBox start: diff --git a/README.md b/README.md index 5f864ad..ed83796 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ See the [CONTRIBUTING](CONTRIBUTING.md) for more information. Each Plugin Version listed below has been tested with its corresponding NetBox Version. | NetBox Version | Plugin Version | -|----------------|----------------| -| 3.2 | 1.0.1 | -| 3.3 | 1.1.1 | -| 3.4 | 1.2.0(coming) | +|:--------------:|:--------------:| +| 3.2 | 1.0.1 | +| 3.3 | 1.1.0 | +| 3.4 | 1.2.0 | ## Installing @@ -81,8 +81,8 @@ To develop this plugin further one can use the included .devcontainer configurat 1. In the WSL terminal, enter `code` to run Visual studio code. 2. Install the devcontainer extension "ms-vscode-remote.remote-containers" 3. Press Ctrl+Shift+P and use the "Dev Container: Clone Repository in Container Volume" function to clone this repository. This will take a while depending on your computer -4. If you'd like the netbox instance to be prepopulated run `make Makefile example_initializers` and `make Makefile load_initializers` -5. Start the netbox instance using `make Makefile all` +4. If you'd like the netbox instance to be prepopulated with example data from [netbox-initializers](https://github.com/tobiasge/netbox-initializers) run `make initializers` +5. Start the netbox instance using `make all` Your netbox instance will be served under 0.0.0.0:8000, so it should now be available under localhost:8000. diff --git a/docs/img/access_list_type_extended.png b/docs/img/access_list_type_extended.png index e0e3f8b..f540d16 100644 Binary files a/docs/img/access_list_type_extended.png and b/docs/img/access_list_type_extended.png differ diff --git a/docs/img/access_list_type_standard.png b/docs/img/access_list_type_standard.png index 2fddca1..0794aeb 100644 Binary files a/docs/img/access_list_type_standard.png and b/docs/img/access_list_type_standard.png differ diff --git a/docs/img/access_lists.png b/docs/img/access_lists.png index 2420b11..98ecf16 100644 Binary files a/docs/img/access_lists.png and b/docs/img/access_lists.png differ diff --git a/docs/img/acl_extended_rules.png b/docs/img/acl_extended_rules.png index 987371c..c21a56b 100644 Binary files a/docs/img/acl_extended_rules.png and b/docs/img/acl_extended_rules.png differ diff --git a/docs/img/acl_host_view.png b/docs/img/acl_host_view.png index 18c559e..15127e6 100644 Binary files a/docs/img/acl_host_view.png and b/docs/img/acl_host_view.png differ diff --git a/docs/img/acl_interface_assignments.png b/docs/img/acl_interface_assignments.png index ce88f82..34031ca 100644 Binary files a/docs/img/acl_interface_assignments.png and b/docs/img/acl_interface_assignments.png differ diff --git a/docs/img/acl_interface_view.png b/docs/img/acl_interface_view.png index 0728749..39431d7 100644 Binary files a/docs/img/acl_interface_view.png and b/docs/img/acl_interface_view.png differ diff --git a/docs/img/acl_standard_rules.png b/docs/img/acl_standard_rules.png index 024f745..6e8efe5 100644 Binary files a/docs/img/acl_standard_rules.png and b/docs/img/acl_standard_rules.png differ diff --git a/netbox_acls/__init__.py b/netbox_acls/__init__.py index 4709253..fa5e548 100644 --- a/netbox_acls/__init__.py +++ b/netbox_acls/__init__.py @@ -17,9 +17,8 @@ class NetBoxACLsConfig(PluginConfig): version = __version__ description = "Manage simple ACLs in NetBox" base_url = "access-lists" - min_version = "3.3.0" - max_version = "3.3.99" - # default_settings = {} + min_version = "3.4.0" + max_version = "3.4.99" config = NetBoxACLsConfig diff --git a/netbox_acls/api/views.py b/netbox_acls/api/views.py index 2db85ba..cdff48d 100644 --- a/netbox_acls/api/views.py +++ b/netbox_acls/api/views.py @@ -28,8 +28,12 @@ class AccessListViewSet(NetBoxModelViewSet): Defines the view set for the django AccessList model & associates it to a view. """ - queryset = models.AccessList.objects.prefetch_related("tags").annotate( - rule_count=Count("aclextendedrules") + Count("aclstandardrules"), + queryset = ( + models.AccessList.objects.prefetch_related("tags") + .annotate( + rule_count=Count("aclextendedrules") + Count("aclstandardrules"), + ) + .prefetch_related("tags") ) serializer_class = AccessListSerializer filterset_class = filtersets.AccessListFilterSet diff --git a/netbox_acls/navigation.py b/netbox_acls/navigation.py index bb96b8f..6d784f5 100644 --- a/netbox_acls/navigation.py +++ b/netbox_acls/navigation.py @@ -2,82 +2,77 @@ Define the plugin menu buttons & the plugin navigation bar enteries. """ -from extras.plugins import PluginMenuButton, PluginMenuItem +from extras.plugins import PluginMenu, PluginMenuButton, PluginMenuItem from utilities.choices import ButtonColorChoices # # Define plugin menu buttons # -accesslist_buttons = [ - PluginMenuButton( - link="plugins:netbox_acls:accesslist_add", - title="Add", - icon_class="mdi mdi-plus-thick", - color=ButtonColorChoices.GREEN, - permissions=["netbox_acls.add_accesslist"], - ), -] - -aclstandardrule_butons = [ - PluginMenuButton( - link="plugins:netbox_acls:aclstandardrule_add", - title="Add", - icon_class="mdi mdi-plus-thick", - color=ButtonColorChoices.GREEN, - permissions=["netbox_acls.add_aclstandardrule"], - ), -] - -aclextendedrule_butons = [ - PluginMenuButton( - link="plugins:netbox_acls:aclextendedrule_add", - title="Add", - icon_class="mdi mdi-plus-thick", - color=ButtonColorChoices.GREEN, - permissions=["netbox_acls.add_aclextendedrule"], - ), -] - -accesslistassignment_buttons = [ - PluginMenuButton( - link="plugins:netbox_acls:aclinterfaceassignment_add", - title="Add", - icon_class="mdi mdi-plus-thick", - color=ButtonColorChoices.GREEN, - permissions=["netbox_acls.add_aclinterfaceassignment"], - ), -] - -# -# Define navigation bar links including the above buttons defined. -# - -menu_items = ( - PluginMenuItem( - link="plugins:netbox_acls:accesslist_list", - link_text="Access Lists", - buttons=accesslist_buttons, - permissions=["netbox_acls.view_accesslist"], - ), - # Comment out Standard Access List rule to force creation in the ACL view - PluginMenuItem( - link="plugins:netbox_acls:aclstandardrule_list", - link_text="ACL Standard Rules", - buttons=aclstandardrule_butons, - permissions=["netbox_acls.view_aclstandardrule"], - ), - # Comment out Extended Access List rule to force creation in the ACL view - PluginMenuItem( - link="plugins:netbox_acls:aclextendedrule_list", - link_text="ACL Extended Rules", - buttons=aclextendedrule_butons, - permissions=["netbox_acls.view_aclextendedrule"], - ), - PluginMenuItem( - link="plugins:netbox_acls:aclinterfaceassignment_list", - link_text="ACL Interface Assignments", - buttons=accesslistassignment_buttons, - permissions=["netbox_acls.view_aclinterfaceassignment"], +menu = PluginMenu( + label="Access Lists", + groups=( + ( + "ACLs", + ( + PluginMenuItem( + link="plugins:netbox_acls:accesslist_list", + link_text="Access Lists", + permissions=["netbox_acls.view_accesslist"], + buttons=( + PluginMenuButton( + link="plugins:netbox_acls:accesslist_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_acls.add_accesslist"], + ), + ), + ), + PluginMenuItem( + link="plugins:netbox_acls:aclstandardrule_list", + link_text="Standard Rules", + permissions=["netbox_acls.view_aclstandardrule"], + buttons=( + PluginMenuButton( + link="plugins:netbox_acls:aclstandardrule_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_acls.add_aclstandardrule"], + ), + ), + ), + PluginMenuItem( + link="plugins:netbox_acls:aclextendedrule_list", + link_text="Extended Rules", + permissions=["netbox_acls.view_aclextendedrule"], + buttons=( + PluginMenuButton( + link="plugins:netbox_acls:aclextendedrule_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_acls.add_aclextendedrule"], + ), + ), + ), + PluginMenuItem( + link="plugins:netbox_acls:aclinterfaceassignment_list", + link_text="Interface Assignments", + permissions=["netbox_acls.view_aclinterfaceassignment"], + buttons=( + PluginMenuButton( + link="plugins:netbox_acls:aclinterfaceassignment_add", + title="Add", + icon_class="mdi mdi-plus-thick", + color=ButtonColorChoices.GREEN, + permissions=["netbox_acls.add_aclinterfaceassignment"], + ), + ), + ), + ), + ), ), + icon_class="mdi mdi-lock", ) diff --git a/netbox_acls/template_content.py b/netbox_acls/template_content.py deleted file mode 100644 index 598e71d..0000000 --- a/netbox_acls/template_content.py +++ /dev/null @@ -1,98 +0,0 @@ -from django.contrib.contenttypes.models import ContentType -from extras.plugins import PluginTemplateExtension - -from .models import AccessList, ACLInterfaceAssignment - -__all__ = ( - "AccessLists", - "ACLInterfaceAssignments", - "DeviceAccessLists", - "VirtualChassisAccessLists", - "VMAccessLists", - "DeviceACLInterfaceAssignments", - "VMAACLInterfaceAssignments", -) - - -class ACLInterfaceAssignments(PluginTemplateExtension): - def right_page(self): - obj = self.context["object"] - - acl_interface_assignments = None - ctype = ContentType.objects.get_for_model(obj) - if ctype.model in ["interface", "vminterface"]: - acl_interface_assignments = ACLInterfaceAssignment.objects.filter( - assigned_object_id=obj.pk, - assigned_object_type=ctype, - ) - if ctype.model == "interface": - parent_type = "device" - parent_id = obj.device.pk - elif ctype.model == "vminterface": - parent_type = "virtual_machine" - parent_id = obj.virtual_machine.pk - else: - parent_type = None - parent_id = None - - return self.render( - "inc/assigned_interface/access_lists.html", - extra_context={ - "acl_interface_assignments": acl_interface_assignments, - "type": ctype.model, - "parent_type": parent_type, - "parent_id": parent_id, - }, - ) - - -class AccessLists(PluginTemplateExtension): - def right_page(self): - obj = self.context["object"] - - access_lists = None - ctype = ContentType.objects.get_for_model(obj) - if ctype.model in ["device", "virtualchassis", "virtualmachine"]: - access_lists = AccessList.objects.filter( - assigned_object_id=obj.pk, - assigned_object_type=ctype, - ) - - return self.render( - "inc/assigned_host/access_lists.html", - extra_context={ - "access_lists": access_lists, - "type": ctype.model - if ctype.model == "device" - else ctype.name.replace(" ", "_"), - }, - ) - - -class DeviceAccessLists(AccessLists): - model = "dcim.device" - - -class VirtualChassisAccessLists(AccessLists): - model = "dcim.virtualchassis" - - -class VMAccessLists(AccessLists): - model = "virtualization.virtualmachine" - - -class DeviceACLInterfaceAssignments(ACLInterfaceAssignments): - model = "dcim.interface" - - -class VMAACLInterfaceAssignments(ACLInterfaceAssignments): - model = "virtualization.vminterface" - - -template_extensions = [ - DeviceAccessLists, - VirtualChassisAccessLists, - VMAccessLists, - DeviceACLInterfaceAssignments, - VMAACLInterfaceAssignments, -] diff --git a/netbox_acls/templates/inc/assigned_host/access_lists.html b/netbox_acls/templates/inc/assigned_host/access_lists.html deleted file mode 100644 index 9738fa9..0000000 --- a/netbox_acls/templates/inc/assigned_host/access_lists.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
- Access Lists -
-
- {% include 'inc/assigned_host/assigned_access_lists.html' %} -
- -
diff --git a/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html b/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html deleted file mode 100644 index f7ce8a3..0000000 --- a/netbox_acls/templates/inc/assigned_host/assigned_access_lists.html +++ /dev/null @@ -1,27 +0,0 @@ -{% if access_lists %} - - - - - - - - - {% for object in access_lists %} - - - - - {% if object.type == 'standard' %} - - {% elif object.type == 'extended' %} - - {% endif %} - - {% endfor %} -
NameTypeDefault ActionRule Count
{{ object|linkify }}{{ object.type|title }}{{ object.default_action|title }}{{ object.aclstandardrules.count|placeholder }}{{ object.aclextendedrules.count|placeholder }}
-{% else %} -
- None found -
-{% endif %} diff --git a/netbox_acls/templates/inc/assigned_interface/access_lists.html b/netbox_acls/templates/inc/assigned_interface/access_lists.html deleted file mode 100644 index 165b0bf..0000000 --- a/netbox_acls/templates/inc/assigned_interface/access_lists.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
- Access Lists -
-
- {% include 'inc/assigned_interface/assigned_access_lists.html' %} -
- -
diff --git a/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html b/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html deleted file mode 100644 index 26bb009..0000000 --- a/netbox_acls/templates/inc/assigned_interface/assigned_access_lists.html +++ /dev/null @@ -1,29 +0,0 @@ -{% if acl_interface_assignments %} - - - - - - - - - - {% for object in acl_interface_assignments %} - - - - - {% if object.access_list.type == 'standard' %} - - {% elif object.access_list.type == 'extended' %} - - {% endif %} - - - {% endfor %} -
NameTypeDefault ActionRule CountDirection
{{ object.access_list|linkify }}{{ object.access_list.type|title }}{{ object.access_list.default_action|title }}{{ object.access_list.aclstandardrules.count|placeholder }}{{ object.access_list.aclextendedrules.count|placeholder }}{{ object.direction|title }}
-{% else %} -
- None -
-{% endif %} diff --git a/netbox_acls/templates/inc/view_tab.html b/netbox_acls/templates/inc/view_tab.html new file mode 100644 index 0000000..2109252 --- /dev/null +++ b/netbox_acls/templates/inc/view_tab.html @@ -0,0 +1,31 @@ +{% extends 'generic/object.html' %} +{% load buttons %} +{% load helpers %} +{% load plugins %} +{% load render_table from django_tables2 %} + +{% block extra_controls %} + {% if perms.netbox_todo.add_accesslist %} + + Add Access List + + {% endif %} +{% endblock extra_controls %} + +{% block content %} + {% include 'inc/table_controls_htmx.html' with table_modal=table_config %} +
+ {% csrf_token %} +
+
+ {% include 'htmx/table.html' %} +
+
+
+{% endblock content %} + +{% block modals %} + {{ block.super }} + {% table_config_form table %} +{% endblock modals %} diff --git a/netbox_acls/urls.py b/netbox_acls/urls.py index f5ed0db..c5f07a1 100644 --- a/netbox_acls/urls.py +++ b/netbox_acls/urls.py @@ -2,8 +2,8 @@ Map Views to URLs. """ -from django.urls import path -from netbox.views.generic import ObjectChangeLogView +from django.urls import include, path +from utilities.urls import get_model_urls from . import models, views @@ -33,12 +33,8 @@ urlpatterns = ( name="accesslist_delete", ), path( - "access-lists//changelog/", - ObjectChangeLogView.as_view(), - name="accesslist_changelog", - kwargs={ - "model": models.AccessList, - }, + "access-lists//", + include(get_model_urls("netbox_acls", "accesslist")), ), # Access List Interface Assignments path( @@ -73,12 +69,8 @@ urlpatterns = ( name="aclinterfaceassignment_delete", ), path( - "interface-assignments//changelog/", - ObjectChangeLogView.as_view(), - name="aclinterfaceassignment_changelog", - kwargs={ - "model": models.ACLInterfaceAssignment, - }, + "interface-assignments//", + include(get_model_urls("netbox_acls", "aclinterfaceassignment")), ), # Standard Access List Rules path( @@ -112,12 +104,8 @@ urlpatterns = ( name="aclstandardrule_delete", ), path( - "standard-rules//changelog/", - ObjectChangeLogView.as_view(), - name="aclstandardrule_changelog", - kwargs={ - "model": models.ACLStandardRule, - }, + "standard-rules//", + include(get_model_urls("netbox_acls", "aclstandardrule")), ), # Extended Access List Rules path( @@ -151,11 +139,7 @@ urlpatterns = ( name="aclextendedrule_delete", ), path( - "extended-rules//changelog/", - ObjectChangeLogView.as_view(), - name="aclextendedrule_changelog", - kwargs={ - "model": models.ACLExtendedRule, - }, + "extended-rules//", + include(get_model_urls("netbox_acls", "aclextendedrule")), ), ) diff --git a/netbox_acls/version.py b/netbox_acls/version.py index a82b376..c68196d 100644 --- a/netbox_acls/version.py +++ b/netbox_acls/version.py @@ -1 +1 @@ -__version__ = "1.1.1" +__version__ = "1.2.0" diff --git a/netbox_acls/views.py b/netbox_acls/views.py index 853f9b9..d986945 100644 --- a/netbox_acls/views.py +++ b/netbox_acls/views.py @@ -3,8 +3,11 @@ Defines the business logic for the plugin. Specifically, all the various interactions with a client. """ +from dcim.models import Device, Interface, VirtualChassis from django.db.models import Count from netbox.views import generic +from utilities.views import ViewTab, register_model_view +from virtualization.models import VirtualMachine, VMInterface from . import choices, filtersets, forms, models, tables @@ -37,12 +40,13 @@ __all__ = ( # +@register_model_view(models.AccessList) class AccessListView(generic.ObjectView): """ Defines the view for the AccessLists django model. """ - queryset = models.AccessList.objects.all() + queryset = models.AccessList.objects.prefetch_related("tags") def get_extra_context(self, request, instance): """ @@ -73,47 +77,121 @@ class AccessListListView(generic.ObjectListView): queryset = models.AccessList.objects.annotate( rule_count=Count("aclextendedrules") + Count("aclstandardrules"), - ) + ).prefetch_related("tags") table = tables.AccessListTable filterset = filtersets.AccessListFilterSet filterset_form = forms.AccessListFilterForm +@register_model_view(models.AccessList, "edit") class AccessListEditView(generic.ObjectEditView): """ Defines the edit view for the AccessLists django model. """ - queryset = models.AccessList.objects.all() + queryset = models.AccessList.objects.prefetch_related("tags") form = forms.AccessListForm template_name = "netbox_acls/accesslist_edit.html" +@register_model_view(models.AccessList, "delete") class AccessListDeleteView(generic.ObjectDeleteView): """ Defines delete view for the AccessLists django model. """ - queryset = models.AccessList.objects.all() + queryset = models.AccessList.objects.prefetch_related("tags") class AccessListBulkDeleteView(generic.BulkDeleteView): - queryset = models.AccessList.objects.all() + queryset = models.AccessList.objects.prefetch_related("tags") filterset = filtersets.AccessListFilterSet table = tables.AccessListTable +class AccessListChildView(generic.ObjectChildrenView): + """ + Defines the child view for the AccessLists model. + """ + + child_model = models.AccessList + table = tables.AccessListTable + filterset = filtersets.AccessListFilterSet + template_name = "inc/view_tab.html" + + def get_extra_context(self, request, instance): + return { + "table_config": self.table.__name__, + "model_type": self.queryset.model._meta.verbose_name.replace(" ", "_"), + "add_url": "plugins:netbox_acls:accesslist_add", + } + + def prep_table_data(self, request, queryset, parent): + return queryset.annotate( + rule_count=Count("aclextendedrules") + Count("aclstandardrules"), + ) + + +@register_model_view(Device, "access_lists") +class DeviceAccessListView(AccessListChildView): + queryset = Device.objects.prefetch_related("tags") + tab = ViewTab( + label="Access Lists", + badge=lambda obj: models.AccessList.objects.filter(device=obj).count(), + permission="netbox_acls.view_accesslist", + ) + + def get_children(self, request, parent): + return self.child_model.objects.restrict(request.user, "view").filter( + device=parent, + ) + + +@register_model_view(VirtualChassis, "access_lists") +class VirtualChassisAccessListView(AccessListChildView): + queryset = VirtualChassis.objects.prefetch_related("tags") + tab = ViewTab( + label="Access Lists", + badge=lambda obj: models.AccessList.objects.filter(virtual_chassis=obj).count(), + permission="netbox_acls.view_accesslist", + ) + + def get_children(self, request, parent): + return self.child_model.objects.restrict(request.user, "view").filter( + virtual_chassis=parent, + ) + + +@register_model_view(VirtualMachine, "access_lists") +class VirtualMachineAccessListView(AccessListChildView): + queryset = VirtualMachine.objects.prefetch_related("tags") + tab = ViewTab( + label="Access Lists", + badge=lambda obj: models.AccessList.objects.filter(virtual_machine=obj).count(), + permission="netbox_acls.view_accesslist", + ) + + def get_children(self, request, parent): + return self.child_model.objects.restrict(request.user, "view").filter( + virtual_machine=parent, + ) + + # # ACLInterfaceAssignment views # +@register_model_view(models.ACLInterfaceAssignment) class ACLInterfaceAssignmentView(generic.ObjectView): """ Defines the view for the ACLInterfaceAssignments django model. """ - queryset = models.ACLInterfaceAssignment.objects.all() + queryset = models.ACLInterfaceAssignment.objects.prefetch_related( + "access_list", + "tags", + ) class ACLInterfaceAssignmentListView(generic.ObjectListView): @@ -121,18 +199,25 @@ class ACLInterfaceAssignmentListView(generic.ObjectListView): Defines the list view for the ACLInterfaceAssignments django model. """ - queryset = models.ACLInterfaceAssignment.objects.all() + queryset = models.ACLInterfaceAssignment.objects.prefetch_related( + "access_list", + "tags", + ) table = tables.ACLInterfaceAssignmentTable filterset = filtersets.ACLInterfaceAssignmentFilterSet filterset_form = forms.ACLInterfaceAssignmentFilterForm +@register_model_view(models.ACLInterfaceAssignment, "edit") class ACLInterfaceAssignmentEditView(generic.ObjectEditView): """ Defines the edit view for the ACLInterfaceAssignments django model. """ - queryset = models.ACLInterfaceAssignment.objects.all() + queryset = models.ACLInterfaceAssignment.objects.prefetch_related( + "access_list", + "tags", + ) form = forms.ACLInterfaceAssignmentForm template_name = "netbox_acls/aclinterfaceassignment_edit.html" @@ -148,31 +233,97 @@ class ACLInterfaceAssignmentEditView(generic.ObjectEditView): } +@register_model_view(models.ACLInterfaceAssignment, "delete") class ACLInterfaceAssignmentDeleteView(generic.ObjectDeleteView): """ Defines delete view for the ACLInterfaceAssignments django model. """ - queryset = models.ACLInterfaceAssignment.objects.all() + queryset = models.ACLInterfaceAssignment.objects.prefetch_related( + "access_list", + "tags", + ) class ACLInterfaceAssignmentBulkDeleteView(generic.BulkDeleteView): - queryset = models.ACLInterfaceAssignment.objects.all() + queryset = models.ACLInterfaceAssignment.objects.prefetch_related( + "access_list", + "tags", + ) filterset = filtersets.ACLInterfaceAssignmentFilterSet table = tables.ACLInterfaceAssignmentTable +class ACLInterfaceAssignmentChildView(generic.ObjectChildrenView): + """ + Defines the child view for the ACLInterfaceAssignments model. + """ + + child_model = models.ACLInterfaceAssignment + table = tables.ACLInterfaceAssignmentTable + filterset = filtersets.ACLInterfaceAssignmentFilterSet + template_name = "inc/view_tab.html" + + def get_extra_context(self, request, instance): + return { + "table_config": self.table.__name__, + "model_type": self.queryset.model._meta.verbose_name.replace(" ", "_"), + "add_url": "plugins:netbox_acls:aclinterfaceassignment_add", + } + + +@register_model_view(Interface, "acl_interface_assignments") +class InterfaceACLInterfaceAssignmentView(ACLInterfaceAssignmentChildView): + queryset = Interface.objects.prefetch_related("device", "tags") + tab = ViewTab( + label="ACL Interface Assignments", + badge=lambda obj: models.ACLInterfaceAssignment.objects.filter( + interface=obj, + ).count(), + permission="netbox_acls.view_aclinterfaceassignment", + ) + + def get_children(self, request, parent): + return self.child_model.objects.restrict(request.user, "view").filter( + interface=parent, + ) + + +@register_model_view(VMInterface, "acl_interface_assignments") +class VirtualMachineInterfaceACLInterfaceAssignmentView( + ACLInterfaceAssignmentChildView, +): + queryset = VMInterface.objects.prefetch_related("virtual_machine", "tags") + tab = ViewTab( + label="ACL Interface Assignments", + badge=lambda obj: models.ACLInterfaceAssignment.objects.filter( + vminterface=obj, + ).count(), + permission="netbox_acls.view_aclinterfaceassignment", + ) + + def get_children(self, request, parent): + return self.child_model.objects.restrict(request.user, "view").filter( + vminterface=parent, + ) + + # # ACLStandardRule views # +@register_model_view(models.ACLStandardRule) class ACLStandardRuleView(generic.ObjectView): """ Defines the view for the ACLStandardRule django model. """ - queryset = models.ACLStandardRule.objects.all() + queryset = models.ACLStandardRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + ) class ACLStandardRuleListView(generic.ObjectListView): @@ -180,18 +331,27 @@ class ACLStandardRuleListView(generic.ObjectListView): Defines the list view for the ACLStandardRule django model. """ - queryset = models.ACLStandardRule.objects.all() + queryset = models.ACLStandardRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + ) table = tables.ACLStandardRuleTable filterset = filtersets.ACLStandardRuleFilterSet filterset_form = forms.ACLStandardRuleFilterForm +@register_model_view(models.ACLStandardRule, "edit") class ACLStandardRuleEditView(generic.ObjectEditView): """ Defines the edit view for the ACLStandardRule django model. """ - queryset = models.ACLStandardRule.objects.all() + queryset = models.ACLStandardRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + ) form = forms.ACLStandardRuleForm def get_extra_addanother_params(self, request): @@ -205,16 +365,25 @@ class ACLStandardRuleEditView(generic.ObjectEditView): } +@register_model_view(models.ACLStandardRule, "delete") class ACLStandardRuleDeleteView(generic.ObjectDeleteView): """ Defines delete view for the ACLStandardRules django model. """ - queryset = models.ACLStandardRule.objects.all() + queryset = models.ACLStandardRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + ) class ACLStandardRuleBulkDeleteView(generic.BulkDeleteView): - queryset = models.ACLStandardRule.objects.all() + queryset = models.ACLStandardRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + ) filterset = filtersets.ACLStandardRuleFilterSet table = tables.ACLStandardRuleTable @@ -224,12 +393,18 @@ class ACLStandardRuleBulkDeleteView(generic.BulkDeleteView): # +@register_model_view(models.ACLExtendedRule) class ACLExtendedRuleView(generic.ObjectView): """ Defines the view for the ACLExtendedRule django model. """ - queryset = models.ACLExtendedRule.objects.all() + queryset = models.ACLExtendedRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + "destination_prefix", + ) class ACLExtendedRuleListView(generic.ObjectListView): @@ -237,18 +412,29 @@ class ACLExtendedRuleListView(generic.ObjectListView): Defines the list view for the ACLExtendedRule django model. """ - queryset = models.ACLExtendedRule.objects.all() + queryset = models.ACLExtendedRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + "destination_prefix", + ) table = tables.ACLExtendedRuleTable filterset = filtersets.ACLExtendedRuleFilterSet filterset_form = forms.ACLExtendedRuleFilterForm +@register_model_view(models.ACLExtendedRule, "edit") class ACLExtendedRuleEditView(generic.ObjectEditView): """ Defines the edit view for the ACLExtendedRule django model. """ - queryset = models.ACLExtendedRule.objects.all() + queryset = models.ACLExtendedRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + "destination_prefix", + ) form = forms.ACLExtendedRuleForm def get_extra_addanother_params(self, request): @@ -262,15 +448,26 @@ class ACLExtendedRuleEditView(generic.ObjectEditView): } +@register_model_view(models.ACLExtendedRule, "delete") class ACLExtendedRuleDeleteView(generic.ObjectDeleteView): """ Defines delete view for the ACLExtendedRules django model. """ - queryset = models.ACLExtendedRule.objects.all() + queryset = models.ACLExtendedRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + "destination_prefix", + ) class ACLExtendedRuleBulkDeleteView(generic.BulkDeleteView): - queryset = models.ACLExtendedRule.objects.all() + queryset = models.ACLExtendedRule.objects.prefetch_related( + "access_list", + "tags", + "source_prefix", + "destination_prefix", + ) filterset = filtersets.ACLExtendedRuleFilterSet table = tables.ACLExtendedRuleTable