Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,24 @@ docker-compose-netbox-plugin-down:

.PHONY: docker-compose-netbox-plugin-test
docker-compose-netbox-plugin-test:
-@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run -u root --rm netbox ./manage.py test $(TEST_FLAGS) --keepdb $(TEST_SELECTOR)
@$(MAKE) docker-compose-netbox-plugin-down
@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run -u root --rm netbox ./manage.py test $(TEST_FLAGS) --keepdb $(TEST_SELECTOR); \
EXIT_CODE=$$?; \
$(MAKE) docker-compose-netbox-plugin-down; \
exit $$EXIT_CODE

.PHONY: docker-compose-netbox-plugin-test-lint
docker-compose-netbox-plugin-test-lint:
-@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run -u root --rm netbox ruff check --output-format=github netbox_diode_plugin
@$(MAKE) docker-compose-netbox-plugin-down
@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run -u root --rm netbox ruff check --output-format=github netbox_diode_plugin; \
EXIT_CODE=$$?; \
$(MAKE) docker-compose-netbox-plugin-down; \
exit $$EXIT_CODE

.PHONY: docker-compose-netbox-plugin-test-cover
docker-compose-netbox-plugin-test-cover:
-@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run --rm -u root -e COVERAGE_FILE=/opt/netbox/netbox/coverage/.coverage netbox sh -c "coverage run --source=netbox_diode_plugin --omit=*/migrations/* ./manage.py test --keepdb $(TEST_SELECTOR) && coverage xml -o /opt/netbox/netbox/coverage/report.xml && coverage report -m | tee /opt/netbox/netbox/coverage/report.txt"
@$(MAKE) docker-compose-netbox-plugin-down
@$(DOCKER_COMPOSE) -f $(DOCKER_PATH)/docker-compose.yaml -f $(DOCKER_PATH)/docker-compose.test.yaml run --rm -u root -e COVERAGE_FILE=/opt/netbox/netbox/coverage/.coverage netbox sh -c "coverage run --source=netbox_diode_plugin --omit=*/migrations/* ./manage.py test --keepdb $(TEST_SELECTOR) && coverage xml -o /opt/netbox/netbox/coverage/report.xml && coverage report -m | tee /opt/netbox/netbox/coverage/report.txt"; \
EXIT_CODE=$$?; \
$(MAKE) docker-compose-netbox-plugin-down; \
exit $$EXIT_CODE

.PHONY: docker-compose-generate-matching-docs
docker-compose-generate-matching-docs:
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
image: netboxcommunity/netbox:v4.4.2-3.4.1-diode-netbox-plugin
build:
context: .
dockerfile: Dockerfile-diode-netbox-plugin
dockerfile: Dockerfile
pull: true
depends_on:
- netbox-postgres
Expand Down
301 changes: 179 additions & 122 deletions docker/netbox/configuration/configuration.py

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions docker/netbox/configuration/extra.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
####
## This file contains extra configuration options that can't be configured
## directly through environment variables.
# This file contains extra configuration options that can't be configured
# directly through environment variables.
####

## Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of
## application errors (assuming correct email settings are provided).
# Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of
# application errors (assuming correct email settings are provided).
# ADMINS = [
# # ['John Doe', '[email protected]'],
# ]


## URL schemes that are allowed within links in NetBox
# URL schemes that are allowed within links in NetBox
# ALLOWED_URL_SCHEMES = (
# 'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc', 'xmpp',
# )

## Enable installed plugins. Add the name of each plugin to the list.
# Enable installed plugins. Add the name of each plugin to the list.
# from netbox.configuration.configuration import PLUGINS
# PLUGINS.append('my_plugin')

## Plugins configuration settings. These settings are used by various plugins that the user may have installed.
## Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
# Plugins configuration settings. These settings are used by various plugins that the user may have installed.
# Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
# from netbox.configuration.configuration import PLUGINS_CONFIG
# PLUGINS_CONFIG['my_plugin'] = {
# 'foo': 'bar',
# 'buzz': 'bazz'
# }


## Remote authentication support
# Remote authentication support
# REMOTE_AUTH_DEFAULT_PERMISSIONS = {}


## By default uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
## class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
# By default uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
# class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
# STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
# STORAGE_CONFIG = {
# 'AWS_ACCESS_KEY_ID': 'Key ID',
Expand All @@ -43,7 +43,7 @@
# }


## This file can contain arbitrary Python code, e.g.:
# This file can contain arbitrary Python code, e.g.:
# from datetime import datetime
# now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
# BANNER_TOP = f'<marquee width="200px">This instance started on {now}.</marquee>'
28 changes: 0 additions & 28 deletions docker/netbox/configuration/ldap/extra.py

This file was deleted.

113 changes: 0 additions & 113 deletions docker/netbox/configuration/ldap/ldap_config.py

This file was deleted.

1 change: 1 addition & 0 deletions docker/netbox/configuration/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
},
}

# # Remove first comment(#) on each line to implement this working logging example.
# # Add LOGLEVEL environment variable to netbox if you use this example & want a different log level.
# from os import environ
Expand Down
19 changes: 0 additions & 19 deletions docker/netbox/configuration/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,3 @@
"netbox_diode_plugin",
"netbox_branching",
]

# PLUGINS_CONFIG = {
# "netbox_diode_plugin": {
# # Auto-provision users for Diode plugin
# "auto_provision_users": True,
#
# # Diode gRPC target for communication with Diode server
# "diode_target_override": "grpc://localhost:8080/diode",
#
# # User allowed for Diode to NetBox communication
# "diode_to_netbox_username": "diode-to-netbox",
#
# # User allowed for NetBox to Diode communication
# "netbox_to_diode_username": "netbox-to-diode",
#
# # User allowed for data ingestion
# "diode_username": "diode-ingestion",
# },
# }
Empty file modified docker/v4.2.3/netbox/docker-entrypoint.sh
100755 → 100644
Empty file.
Empty file modified docker/v4.2.3/netbox/launch-netbox.sh
100755 → 100644
Empty file.
3 changes: 2 additions & 1 deletion netbox_diode_plugin/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from django.urls import include, path
from netbox.api.routers import NetBoxRouter

from .views import ApplyChangeSetView, GenerateDiffView
from .views import ApplyChangeSetView, GenerateDiffView, GetDefaultBranchView

router = NetBoxRouter()

urlpatterns = [
path("apply-change-set/", ApplyChangeSetView.as_view()),
path("generate-diff/", GenerateDiffView.as_view()),
path("default-branch/", GetDefaultBranchView.as_view()),
path("", include(router.urls)),
]
70 changes: 60 additions & 10 deletions netbox_diode_plugin/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,35 @@ def post(self, request, *args, **kwargs):
traceback.print_exc()
raise

def _get_branch_schema_id(self, request):
"""Get branch schema ID from request header or settings."""
branch_schema_id = request.headers.get("X-NetBox-Branch")

# If no branch specified in header, check for default branch in settings
if not branch_schema_id and Branch is not None:
try:
from netbox_diode_plugin.models import Setting
settings = Setting.objects.first()
if settings and settings.branch:
branch_schema_id = settings.branch.schema_id
logger.debug(
f"Using default branch from settings: {settings.branch.name} ({branch_schema_id})"
)
except Exception as e:
logger.warning(f"Could not retrieve default branch from settings: {e}")

return branch_schema_id

def _add_branch_to_result(self, result, branch_schema_id):
"""Add branch information to the result if branch is available."""
if branch_schema_id and Branch is not None:
try:
branch = Branch.objects.get(schema_id=branch_schema_id)
result.change_set.branch = {"id": branch.schema_id, "name": branch.name}
except Branch.DoesNotExist:
sanitized_branch_id = branch_schema_id.replace('\n', '').replace('\r', '')
logger.warning(f"Branch with ID {sanitized_branch_id} does not exist")

def _post(self, request, *args, **kwargs):
entity = request.data.get("entity")
object_type = request.data.get("object_type")
Expand Down Expand Up @@ -128,16 +157,8 @@ def _post(self, request, *args, **kwargs):
)

result = generate_changeset(original_entity_data, object_type)
branch_schema_id = request.headers.get("X-NetBox-Branch")

# If branch schema ID is provided and branching plugin is installed, get branch name
if branch_schema_id and Branch is not None:
try:
branch = Branch.objects.get(schema_id=branch_schema_id)
result.change_set.branch = {"id": branch.schema_id, "name": branch.name}
except Branch.DoesNotExist:
sanitized_branch_id = branch_schema_id.replace('\n', '').replace('\r', '')
logger.warning(f"Branch with ID {sanitized_branch_id} does not exist")
branch_schema_id = self._get_branch_schema_id(request)
self._add_branch_to_result(result, branch_schema_id)

return Response(result.to_dict(), status=result.get_status_code())

Expand Down Expand Up @@ -190,3 +211,32 @@ def _post(self, request, *args, **kwargs):
)

return Response(result.to_dict(), status=result.get_status_code())


class GetDefaultBranchView(views.APIView):
"""GetDefaultBranch view."""

authentication_classes = [DiodeOAuth2Authentication]
permission_classes = [IsAuthenticated, require_scopes(SCOPE_NETBOX_READ)]

def get(self, request, *args, **kwargs):
"""Get default branch from settings."""
branch_data = None

# Check for default branch in settings
if Branch is not None:
try:
from netbox_diode_plugin.models import Setting
settings = Setting.objects.first()
if settings and settings.branch:
branch_data = {
"id": settings.branch.schema_id,
"name": settings.branch.name
}
logger.debug(
f"Default branch from settings: {settings.branch.name} ({settings.branch.schema_id})"
)
except Exception as e:
logger.warning(f"Could not retrieve default branch from settings: {e}")

return Response({"branch": branch_data})
Loading