diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 0821a2e15ced..88e542bc7382 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -658,6 +658,7 @@ in { networking.networkmanager = handleTest ./networking/networkmanager.nix {}; netbox_3_6 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_3_6; }; netbox_3_7 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_3_7; }; + netbox_4_0 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_4_0; }; netbox-upgrade = handleTest ./web-apps/netbox-upgrade.nix {}; # TODO: put in networking.nix after the test becomes more complete networkingProxy = handleTest ./networking-proxy.nix {}; diff --git a/nixos/tests/web-apps/netbox.nix b/nixos/tests/web-apps/netbox.nix index 233f16a8fe0d..2fdd70cfb1bf 100644 --- a/nixos/tests/web-apps/netbox.nix +++ b/nixos/tests/web-apps/netbox.nix @@ -132,7 +132,7 @@ in import ../make-test-python.nix ({ lib, pkgs, netbox, ... }: { testScript = let changePassword = pkgs.writeText "change-password.py" '' - from django.contrib.auth.models import User + from users.models import User u = User.objects.get(username='netbox') u.set_password('netbox') u.save() @@ -171,11 +171,6 @@ in import ../make-test-python.nix ({ lib, pkgs, netbox, ... }: { machine.succeed("curl -sSfL http://localhost/static/netbox.js") machine.succeed("curl -sSfL http://localhost/static/docs/") - with subtest("Can interact with API"): - json.loads( - machine.succeed("curl -sSfL -H 'Accept: application/json' 'http://localhost/api/'") - ) - def login(username: str, password: str): encoded_data = json.dumps({"username": username, "password": password}) uri = "/users/tokens/provision/" diff --git a/pkgs/by-name/ne/netbox_4_0/custom-static-root.patch b/pkgs/by-name/ne/netbox_4_0/custom-static-root.patch new file mode 100644 index 000000000000..c9219fa2b871 --- /dev/null +++ b/pkgs/by-name/ne/netbox_4_0/custom-static-root.patch @@ -0,0 +1,13 @@ +diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py +index 2de06dd10..00406af48 100644 +--- a/netbox/netbox/settings.py ++++ b/netbox/netbox/settings.py +@@ -410,7 +412,7 @@ USE_X_FORWARDED_HOST = True + X_FRAME_OPTIONS = 'SAMEORIGIN' + + # Static files (CSS, JavaScript, Images) +-STATIC_ROOT = BASE_DIR + '/static' ++STATIC_ROOT = getattr(configuration, 'STATIC_ROOT', os.path.join(BASE_DIR, 'static')).rstrip('/') + STATIC_URL = f'/{BASE_PATH}static/' + STATICFILES_DIRS = ( + os.path.join(BASE_DIR, 'project-static', 'dist'), diff --git a/pkgs/by-name/ne/netbox_4_0/django-5.1.patch b/pkgs/by-name/ne/netbox_4_0/django-5.1.patch new file mode 100644 index 000000000000..3976e79067a0 --- /dev/null +++ b/pkgs/by-name/ne/netbox_4_0/django-5.1.patch @@ -0,0 +1,81 @@ +diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py +index f2cf0b721..a17b6712d 100644 +--- a/netbox/extras/forms/bulk_import.py ++++ b/netbox/extras/forms/bulk_import.py +@@ -194,7 +194,7 @@ class Meta: + model = EventRule + fields = ( + 'name', 'description', 'enabled', 'conditions', 'object_types', 'type_create', 'type_update', +- 'type_delete', 'type_job_start', 'type_job_end', 'action_type', 'action_object', 'comments', 'tags' ++ 'type_delete', 'type_job_start', 'type_job_end', 'action_type', 'comments', 'tags' + ) + + def clean(self): +diff --git a/netbox/extras/migrations/0002_squashed_0059.py b/netbox/extras/migrations/0002_squashed_0059.py +index 98bed255a..a403a0e19 100644 +--- a/netbox/extras/migrations/0002_squashed_0059.py ++++ b/netbox/extras/migrations/0002_squashed_0059.py +@@ -131,10 +131,6 @@ class Migration(migrations.Migration): + name='webhook', + unique_together={('payload_url', 'type_create', 'type_update', 'type_delete')}, + ), +- migrations.AlterIndexTogether( +- name='taggeditem', +- index_together={('content_type', 'object_id')}, +- ), + migrations.AlterUniqueTogether( + name='exporttemplate', + unique_together={('content_type', 'name')}, +diff --git a/netbox/extras/migrations/0087_squashed_0098.py b/netbox/extras/migrations/0087_squashed_0098.py +index 55f276ecd..bbe7f79f5 100644 +--- a/netbox/extras/migrations/0087_squashed_0098.py ++++ b/netbox/extras/migrations/0087_squashed_0098.py +@@ -98,10 +98,9 @@ class Migration(migrations.Migration): + name='object_types', + field=models.ManyToManyField(blank=True, related_name='+', to='contenttypes.contenttype'), + ), +- migrations.RenameIndex( ++ migrations.AddIndex( + model_name='taggeditem', +- new_name='extras_tagg_content_717743_idx', +- old_fields=('content_type', 'object_id'), ++ index=models.Index(fields=['content_type', 'object_id'], name='extras_tagg_content_717743_idx'), + ), + migrations.CreateModel( + name='Bookmark', +diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py +index f5e3bca30..4f96bac71 100644 +--- a/netbox/ipam/forms/model_forms.py ++++ b/netbox/ipam/forms/model_forms.py +@@ -588,7 +588,7 @@ class VLANGroupForm(NetBoxModelForm): + class Meta: + model = VLANGroup + fields = [ +- 'name', 'slug', 'description', 'min_vid', 'max_vid', 'scope_type', 'scope', 'tags', ++ 'name', 'slug', 'description', 'min_vid', 'max_vid', 'scope_type', 'tags', + ] + + def __init__(self, *args, **kwargs): +diff --git a/netbox/vpn/forms/model_forms.py b/netbox/vpn/forms/model_forms.py +index a17ca9a5e..dee98afd3 100644 +--- a/netbox/vpn/forms/model_forms.py ++++ b/netbox/vpn/forms/model_forms.py +@@ -258,7 +258,7 @@ class TunnelTerminationForm(NetBoxModelForm): + class Meta: + model = TunnelTermination + fields = [ +- 'tunnel', 'role', 'termination', 'outside_ip', 'tags', ++ 'tunnel', 'role', 'outside_ip', 'tags', + ] + + def __init__(self, *args, initial=None, **kwargs): +diff --git a/requirements.txt b/requirements.txt +index 09f23871c..57f167dae 100644 +--- a/requirements.txt ++++ b/requirements.txt +@@ -1,4 +1,4 @@ +-Django==5.0.9 ++Django==5.1.2 + django-cors-headers==4.4.0 + django-debug-toolbar==4.4.6 + django-filter==24.2 diff --git a/pkgs/by-name/ne/netbox_4_0/package.nix b/pkgs/by-name/ne/netbox_4_0/package.nix new file mode 100644 index 000000000000..81b05c2679d6 --- /dev/null +++ b/pkgs/by-name/ne/netbox_4_0/package.nix @@ -0,0 +1,132 @@ +{ + lib, + fetchFromGitHub, + python3, + plugins ? _ps: [ ], + nixosTests, +}: +let + py = python3.override { + packageOverrides = _final: prev: { django = prev.django_5; }; + }; + + extraBuildInputs = plugins py.pkgs; +in +py.pkgs.buildPythonApplication rec { + pname = "netbox"; + version = "4.0.11"; + + format = "other"; + + src = fetchFromGitHub { + owner = "netbox-community"; + repo = "netbox"; + rev = "refs/tags/v${version}"; + hash = "sha256-0yEz7v5RL1+cqbGDyuyEsywFonJQfPdVIQdL0qLyc04="; + }; + + patches = [ + ./custom-static-root.patch + # From https://github.com/netbox-community/netbox/pull/17620 + ./django-5.1.patch + ]; + + propagatedBuildInputs = + ( + with py.pkgs; + [ + django + django-cors-headers + django-debug-toolbar + django-filter + django-graphiql-debug-toolbar + django-htmx + django-mptt + django-pglocks + django-prometheus + django-redis + django-rq + django-tables2 + django-taggit + django-timezone-field + djangorestframework + drf-spectacular + drf-spectacular-sidecar + feedparser + jinja2 + markdown + netaddr + nh3 + pillow + psycopg + psycopg.optional-dependencies.c + psycopg.optional-dependencies.pool + pyyaml + requests + social-auth-core + social-auth-app-django + strawberry-graphql + strawberry-django + svgwrite + tablib + + # Optional dependencies, kept here for backward compatibility + + # for the S3 data source backend + boto3 + # for Git data source backend + dulwich + # for error reporting + sentry-sdk + ] + ++ social-auth-core.passthru.optional-dependencies.openidconnect + ) + ++ extraBuildInputs; + + buildInputs = with py.pkgs; [ + mkdocs-material + mkdocs-material-extensions + mkdocstrings + mkdocstrings-python + ]; + + nativeBuildInputs = [ py.pkgs.mkdocs ]; + + postBuild = '' + PYTHONPATH=$PYTHONPATH:netbox/ + python -m mkdocs build + ''; + + installPhase = '' + mkdir -p $out/opt/netbox + cp -r . $out/opt/netbox + chmod +x $out/opt/netbox/netbox/manage.py + makeWrapper $out/opt/netbox/netbox/manage.py $out/bin/netbox \ + --prefix PYTHONPATH : "$PYTHONPATH" + ''; + + passthru = { + python = python3; + # PYTHONPATH of all dependencies used by the package + pythonPath = py.pkgs.makePythonPath propagatedBuildInputs; + inherit (py.pkgs) gunicorn; + tests = { + netbox = nixosTests.netbox_4_0; + }; + }; + + meta = { + homepage = "https://github.com/netbox-community/netbox"; + description = "IP address management (IPAM) and data center infrastructure management (DCIM) tool"; + mainProgram = "netbox"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ + minijackson + n0emis + raitobezarius + ]; + knownVulnerabilities = [ + "Netbox version ${version} is EOL; please upgrade by following the current release notes instructions." + ]; + }; +}