From 020e0adeb49a2f03ffdcc3e2903e4c72c661f5d0 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Mon, 22 Feb 2021 15:53:02 -0500 Subject: [PATCH 01/44] update .gitignore to keep extra.py in ldap config --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 07859bb..04dcc7e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ configuration/* !configuration/extra.py configuration/ldap/* !configuration/ldap/ldap_config.py +!configuration/ldap/extra.py prometheus.yml super-linter.log From 22186b267daef78c679a4dc2ae2ef2d9865fc131 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Mon, 22 Feb 2021 15:55:40 -0500 Subject: [PATCH 02/44] do not set AUTH_LDAP_MIRROR_GROUPS if not defined --- configuration/ldap/ldap_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configuration/ldap/ldap_config.py b/configuration/ldap/ldap_config.py index 3071b45..f316ac0 100644 --- a/configuration/ldap/ldap_config.py +++ b/configuration/ldap/ldap_config.py @@ -77,7 +77,8 @@ if AUTH_LDAP_REQUIRE_GROUP is not None: # For more granular permissions, we can map LDAP groups to Django groups. AUTH_LDAP_FIND_GROUP_PERMS = environ.get('AUTH_LDAP_FIND_GROUP_PERMS', 'True').lower() == 'true' -AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true' +if environ.get('AUTH_LDAP_MIRROR_GROUPS') is not None: + AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true' # Cache groups for one hour to reduce LDAP traffic AUTH_LDAP_CACHE_TIMEOUT = int(environ.get('AUTH_LDAP_CACHE_TIMEOUT', 3600)) From 0dec4d8df4a044f08d5e7ca6b75cb51562fc1785 Mon Sep 17 00:00:00 2001 From: Ryan Merolle Date: Mon, 22 Feb 2021 16:00:08 -0500 Subject: [PATCH 03/44] Add extra.py example for ldap config --- configuration/ldap/extra.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 configuration/ldap/extra.py diff --git a/configuration/ldap/extra.py b/configuration/ldap/extra.py new file mode 100644 index 0000000..2edae86 --- /dev/null +++ b/configuration/ldap/extra.py @@ -0,0 +1,8 @@ +#### +## This file contains extra configuration options that can't be configured +## directly through environment variables. +#### + +# import ldap + +# AUTH_LDAP_MIRROR_GROUPS = ["netbox-group-1", "netbox-group-2"] From edb61f3d9007d281cf5e68d1ec21b14955b4c311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Thu, 11 Mar 2021 18:10:09 +0100 Subject: [PATCH 04/44] Sponsor Message --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fa0c9bd..6cfdd95 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,7 @@ It runs NetBox's own unit tests and ensures that all initializers work: IMAGE=netboxcommunity/netbox:latest ./test.sh ``` -## About +## Support -This repository is currently maintained and funded by [nxt][nxt]. - -[nxt]: https://nxt.engineering/en/ +This repository is currently maintained by the community. +Please consider sponsoring the maintainers of this project. From ce6fe5cb83691eeb28c094031279287c43d62211 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 26 Mar 2021 11:37:33 +0000 Subject: [PATCH 05/44] Update dependency ruamel.yaml to v0.17.0 --- requirements-container.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-container.txt b/requirements-container.txt index 05af225..f1d4c26 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,4 +1,4 @@ napalm==3.2.0 -ruamel.yaml==0.16.13 +ruamel.yaml==0.17.0 django-auth-ldap==2.3.0 django-storages[azure,boto3,dropbox,google,libcloud,sftp]==1.11.1 From cca79b5dbdfa6497957557cd897a31388cd4f0fd Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 29 Mar 2021 17:03:30 +0000 Subject: [PATCH 06/44] Update dependency ruamel.yaml to v0.17.2 --- requirements-container.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-container.txt b/requirements-container.txt index f1d4c26..f925cb6 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,4 +1,4 @@ napalm==3.2.0 -ruamel.yaml==0.17.0 +ruamel.yaml==0.17.2 django-auth-ldap==2.3.0 django-storages[azure,boto3,dropbox,google,libcloud,sftp]==1.11.1 From a2e33c166db166f2c9ff4f9d3c33c71b60fc164b Mon Sep 17 00:00:00 2001 From: Marcus Crane Date: Thu, 1 Apr 2021 18:48:13 +1300 Subject: [PATCH 07/44] Fix link name reference if content type is invalid Currently, the name of a custom link is referenced as if it is an object attribute which causes a break due to it actually being a dictionary. This minor change means that the startup script won't *ahem* fail upon failing :) Signed-Off-by: Marcus Crane --- startup_scripts/280_custom_links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup_scripts/280_custom_links.py b/startup_scripts/280_custom_links.py index 459ede3..b611763 100644 --- a/startup_scripts/280_custom_links.py +++ b/startup_scripts/280_custom_links.py @@ -23,7 +23,7 @@ for link in custom_links: if link["content_type_id"] is None: print( "⚠️ Unable to create Custom Link '{0}': The content_type '{1}' is unknown".format( - link.name, content_type + link.get('name'), content_type ) ) continue From 594408643525e1bdaa5e74e5f18959d9890ca2e3 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 09:15:21 +0200 Subject: [PATCH 08/44] Rack groups have been renamed to locations --- initializers/{rack_groups.yml => locations.yml} | 0 initializers/power_panels.yml | 2 +- initializers/racks.yml | 2 +- startup_scripts/{075_rack_groups.py => 075_locations.py} | 8 ++++---- startup_scripts/080_racks.py | 4 ++-- startup_scripts/330_power_panels.py | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) rename initializers/{rack_groups.yml => locations.yml} (100%) rename startup_scripts/{075_rack_groups.py => 075_locations.py} (60%) diff --git a/initializers/rack_groups.yml b/initializers/locations.yml similarity index 100% rename from initializers/rack_groups.yml rename to initializers/locations.yml diff --git a/initializers/power_panels.yml b/initializers/power_panels.yml index 1205851..a670ba7 100644 --- a/initializers/power_panels.yml +++ b/initializers/power_panels.yml @@ -2,4 +2,4 @@ # site: AMS 1 # - name: power panel SING 1 # site: SING 1 -# rack_group: cage 101 +# location: cage 101 diff --git a/initializers/racks.yml b/initializers/racks.yml index 379553d..9071e19 100644 --- a/initializers/racks.yml +++ b/initializers/racks.yml @@ -32,7 +32,7 @@ # text_field: Description # - site: SING 1 # name: rack-03 -# group: cage 101 +# location: cage 101 # role: Role 3 # type: 4-post-cabinet # width: 19 diff --git a/startup_scripts/075_rack_groups.py b/startup_scripts/075_locations.py similarity index 60% rename from startup_scripts/075_rack_groups.py rename to startup_scripts/075_locations.py index 3974b56..d8a2c5a 100644 --- a/startup_scripts/075_rack_groups.py +++ b/startup_scripts/075_locations.py @@ -1,9 +1,9 @@ import sys -from dcim.models import RackGroup, Site +from dcim.models import Location, Site from startup_script_utils import load_yaml -rack_groups = load_yaml("/opt/netbox/initializers/rack_groups.yml") +rack_groups = load_yaml("/opt/netbox/initializers/locations.yml") if rack_groups is None: sys.exit() @@ -17,7 +17,7 @@ for params in rack_groups: query = {field: params.pop(assoc)} params[assoc] = model.objects.get(**query) - rack_group, created = RackGroup.objects.get_or_create(**params) + location, created = Location.objects.get_or_create(**params) if created: - print("🎨 Created rack group", rack_group.name) + print("🎨 Created location", location.name) diff --git a/startup_scripts/080_racks.py b/startup_scripts/080_racks.py index 087b3f9..eb9bcf9 100644 --- a/startup_scripts/080_racks.py +++ b/startup_scripts/080_racks.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Rack, RackGroup, RackRole, Site +from dcim.models import Rack, Location, RackRole, Site from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values from tenancy.models import Tenant @@ -14,7 +14,7 @@ required_assocs = {"site": (Site, "name")} optional_assocs = { "role": (RackRole, "name"), "tenant": (Tenant, "name"), - "group": (RackGroup, "name"), + "location": (Location, "name"), } for params in racks: diff --git a/startup_scripts/330_power_panels.py b/startup_scripts/330_power_panels.py index bfde18f..370a7b6 100644 --- a/startup_scripts/330_power_panels.py +++ b/startup_scripts/330_power_panels.py @@ -1,6 +1,6 @@ import sys -from dcim.models import PowerPanel, RackGroup, Site +from dcim.models import PowerPanel, Location, Site from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values power_panels = load_yaml("/opt/netbox/initializers/power_panels.yml") @@ -10,7 +10,7 @@ if power_panels is None: required_assocs = {"site": (Site, "name")} -optional_assocs = {"rack_group": (RackGroup, "name")} +optional_assocs = {"location": (Location, "name")} for params in power_panels: custom_field_data = pop_custom_fields(params) From 45824ba4f31b1e77ff149a7d3ead84b6bf3a7117 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 09:57:59 +0200 Subject: [PATCH 09/44] Devices can be added to locations --- initializers/devices.yml | 9 ++++++ startup_scripts/140_devices.py | 3 +- startup_scripts/145_devices.py | 51 ---------------------------------- 3 files changed, 11 insertions(+), 52 deletions(-) delete mode 100644 startup_scripts/145_devices.py diff --git a/initializers/devices.yml b/initializers/devices.yml index 0de0504..8324c36 100644 --- a/initializers/devices.yml +++ b/initializers/devices.yml @@ -42,3 +42,12 @@ # 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/startup_scripts/140_devices.py b/startup_scripts/140_devices.py index 597db0c..3e26c41 100644 --- a/startup_scripts/140_devices.py +++ b/startup_scripts/140_devices.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Device, DeviceRole, DeviceType, Platform, Rack, Site +from dcim.models import Device, DeviceRole, DeviceType, Platform, Rack, Site, Location from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values from tenancy.models import Tenant from virtualization.models import Cluster @@ -21,6 +21,7 @@ optional_assocs = { "platform": (Platform, "name"), "rack": (Rack, "name"), "cluster": (Cluster, "name"), + "location": (Location, "name"), } for params in devices: diff --git a/startup_scripts/145_devices.py b/startup_scripts/145_devices.py deleted file mode 100644 index 597db0c..0000000 --- a/startup_scripts/145_devices.py +++ /dev/null @@ -1,51 +0,0 @@ -import sys - -from dcim.models import Device, DeviceRole, DeviceType, Platform, Rack, Site -from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values -from tenancy.models import Tenant -from virtualization.models import Cluster - -devices = load_yaml("/opt/netbox/initializers/devices.yml") - -if devices is None: - sys.exit() - -required_assocs = { - "device_role": (DeviceRole, "name"), - "device_type": (DeviceType, "model"), - "site": (Site, "name"), -} - -optional_assocs = { - "tenant": (Tenant, "name"), - "platform": (Platform, "name"), - "rack": (Rack, "name"), - "cluster": (Cluster, "name"), -} - -for params in devices: - custom_field_data = pop_custom_fields(params) - - # primary ips are handled later in `270_primary_ips.py` - params.pop("primary_ip4", None) - params.pop("primary_ip6", None) - - for assoc, details in required_assocs.items(): - model, field = details - query = {field: params.pop(assoc)} - - params[assoc] = model.objects.get(**query) - - for assoc, details in optional_assocs.items(): - if assoc in params: - model, field = details - query = {field: params.pop(assoc)} - - params[assoc] = model.objects.get(**query) - - device, created = Device.objects.get_or_create(**params) - - if created: - set_custom_fields_values(device, custom_field_data) - - print("πŸ–₯️ Created device", device.name) From b18e4aaf92b00edfc032acf7fdad1a8009c982ec Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 10:57:14 +0200 Subject: [PATCH 10/44] Fix super-linter on PRs See: https://github.com/github/super-linter#example-connecting-github-action-workflow --- .github/workflows/push.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 43c6482..3ea6214 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -14,6 +14,9 @@ jobs: name: Checks syntax of our code steps: - uses: actions/checkout@v2 + with: + # Full git history is needed to get a proper list of changed files within `super-linter` + fetch-depth: 0 - uses: actions/setup-python@v2 - name: Lint Code Base uses: github/super-linter@v3 From 1c4b6741ac0fe2abd4c2656fcdeb26c2d39b285f Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 11:01:01 +0200 Subject: [PATCH 11/44] Fixed isort issues --- startup_scripts/080_racks.py | 2 +- startup_scripts/140_devices.py | 2 +- startup_scripts/330_power_panels.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/startup_scripts/080_racks.py b/startup_scripts/080_racks.py index eb9bcf9..b2cfc80 100644 --- a/startup_scripts/080_racks.py +++ b/startup_scripts/080_racks.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Rack, Location, RackRole, Site +from dcim.models import Location, Rack, RackRole, Site from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values from tenancy.models import Tenant diff --git a/startup_scripts/140_devices.py b/startup_scripts/140_devices.py index 3e26c41..423b7c9 100644 --- a/startup_scripts/140_devices.py +++ b/startup_scripts/140_devices.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Device, DeviceRole, DeviceType, Platform, Rack, Site, Location +from dcim.models import Device, DeviceRole, DeviceType, Location, Platform, Rack, Site from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values from tenancy.models import Tenant from virtualization.models import Cluster diff --git a/startup_scripts/330_power_panels.py b/startup_scripts/330_power_panels.py index 370a7b6..8542435 100644 --- a/startup_scripts/330_power_panels.py +++ b/startup_scripts/330_power_panels.py @@ -1,6 +1,6 @@ import sys -from dcim.models import PowerPanel, Location, Site +from dcim.models import Location, PowerPanel, Site from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values power_panels = load_yaml("/opt/netbox/initializers/power_panels.yml") From 9874cef369ba91e26e09b4151b704e20c22480c2 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 15:18:33 +0200 Subject: [PATCH 12/44] VLAN Groups can be scoped to multiple types --- initializers/vlan_groups.yml | 22 ++++++++++++++++++++-- startup_scripts/200_vlan_groups.py | 18 +++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/initializers/vlan_groups.yml b/initializers/vlan_groups.yml index 3e0bb00..a40fd0a 100644 --- a/initializers/vlan_groups.yml +++ b/initializers/vlan_groups.yml @@ -1,6 +1,24 @@ # - name: VLAN group 1 -# site: AMS 1 +# scope_type: "dcim.region" +# scope: Amsterdam # slug: vlan-group-1 # - name: VLAN group 2 -# site: AMS 1 +# 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/startup_scripts/200_vlan_groups.py b/startup_scripts/200_vlan_groups.py index 7b72b2d..6dda214 100644 --- a/startup_scripts/200_vlan_groups.py +++ b/startup_scripts/200_vlan_groups.py @@ -1,6 +1,6 @@ import sys -from dcim.models import Site +from django.contrib.contenttypes.models import ContentType from ipam.models import VLANGroup from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values @@ -9,7 +9,7 @@ vlan_groups = load_yaml("/opt/netbox/initializers/vlan_groups.yml") if vlan_groups is None: sys.exit() -optional_assocs = {"site": (Site, "name")} +optional_assocs = {"scope": (None, "name")} for params in vlan_groups: custom_field_data = pop_custom_fields(params) @@ -18,9 +18,17 @@ for params in vlan_groups: if assoc in params: model, field = details query = {field: params.pop(assoc)} - - params[assoc] = model.objects.get(**query) - + # Get model from Contenttype + scope_type = params.pop("scope_type", None) + if not scope_type: + print("scope_type is missing from VLAN Group") + continue + app_label, model = str(scope_type).split(".") + ct = ContentType.objects.get(app_label=app_label, model=model) + if not ct: + print(f"ContentType for app_label = '{app_label}' and model = '{model}' not found") + continue + params["scope_id"] = ct.model_class().objects.get(**query).id vlan_group, created = VLANGroup.objects.get_or_create(**params) if created: From 3673196c16fcbebd0b6b46a61887422ff435d9c8 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 7 Apr 2021 15:19:14 +0200 Subject: [PATCH 13/44] Fields in Custom links have been renamed --- initializers/custom_links.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/initializers/custom_links.yml b/initializers/custom_links.yml index f1b275c..eb733ca 100644 --- a/initializers/custom_links.yml +++ b/initializers/custom_links.yml @@ -10,12 +10,12 @@ ## Examples: # - name: link_to_repo -# text: 'Link to Netbox Docker' -# url: 'https://github.com/netbox-community/netbox-docker' +# 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 -# text: 'Link to localhost' -# url: 'http://localhost' +# link_text: 'Link to localhost' +# link_url: 'http://localhost' # new_window: True # content_type: device From a572d5f5de110c561f5d4758ec0c7703d4d352af Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 7 Apr 2021 20:52:56 +0000 Subject: [PATCH 14/44] Update dependency ruamel.yaml to v0.17.4 --- requirements-container.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-container.txt b/requirements-container.txt index f925cb6..a4b538a 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,4 +1,4 @@ napalm==3.2.0 -ruamel.yaml==0.17.2 +ruamel.yaml==0.17.4 django-auth-ldap==2.3.0 django-storages[azure,boto3,dropbox,google,libcloud,sftp]==1.11.1 From f637de88f06e6ac5bc754a33899afc30eb24f088 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Tue, 13 Apr 2021 14:31:05 +0200 Subject: [PATCH 15/44] Improved error logging --- initializers/vlan_groups.yml | 12 ++++++------ startup_scripts/200_vlan_groups.py | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/initializers/vlan_groups.yml b/initializers/vlan_groups.yml index a40fd0a..facd34f 100644 --- a/initializers/vlan_groups.yml +++ b/initializers/vlan_groups.yml @@ -1,24 +1,24 @@ # - name: VLAN group 1 -# scope_type: "dcim.region" +# scope_type: dcim.region # scope: Amsterdam # slug: vlan-group-1 # - name: VLAN group 2 -# scope_type: "dcim.site" +# scope_type: dcim.site # scope: AMS 1 # slug: vlan-group-2 # - name: VLAN group 3 -# scope_type: "dcim.location" +# scope_type: dcim.location # scope: cage 101 # slug: vlan-group-3 # - name: VLAN group 4 -# scope_type: "dcim.rack" +# scope_type: dcim.rack # scope: rack-01 # slug: vlan-group-4 # - name: VLAN group 5 -# scope_type: "virtualization.cluster" +# scope_type: virtualization.cluster # scope: cluster1 # slug: vlan-group-5 # - name: VLAN group 6 -# scope_type: "virtualization.clustergroup" +# scope_type: virtualization.clustergroup # scope: Group 1 # slug: vlan-group-6 diff --git a/startup_scripts/200_vlan_groups.py b/startup_scripts/200_vlan_groups.py index 6dda214..eb61023 100644 --- a/startup_scripts/200_vlan_groups.py +++ b/startup_scripts/200_vlan_groups.py @@ -21,12 +21,15 @@ for params in vlan_groups: # Get model from Contenttype scope_type = params.pop("scope_type", None) if not scope_type: - print("scope_type is missing from VLAN Group") + print(f"VLAN Group '{params['name']}': scope_type is missing from VLAN Group") continue app_label, model = str(scope_type).split(".") - ct = ContentType.objects.get(app_label=app_label, model=model) + ct = ContentType.objects.filter(app_label=app_label, model=model).first() if not ct: - print(f"ContentType for app_label = '{app_label}' and model = '{model}' not found") + print( + f"VLAN Group '{params['name']}': ContentType for " + + "app_label = '{app_label}' and model = '{model}' not found" + ) continue params["scope_id"] = ct.model_class().objects.get(**query).id vlan_group, created = VLANGroup.objects.get_or_create(**params) From 752f592e5894b8116cdcfac592bef52add674f8f Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Tue, 13 Apr 2021 15:50:23 +0200 Subject: [PATCH 16/44] Fixed Python f-string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christian MΓ€der --- startup_scripts/200_vlan_groups.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup_scripts/200_vlan_groups.py b/startup_scripts/200_vlan_groups.py index eb61023..2a4a33d 100644 --- a/startup_scripts/200_vlan_groups.py +++ b/startup_scripts/200_vlan_groups.py @@ -28,7 +28,7 @@ for params in vlan_groups: if not ct: print( f"VLAN Group '{params['name']}': ContentType for " - + "app_label = '{app_label}' and model = '{model}' not found" + + f"app_label = '{app_label}' and model = '{model}' not found" ) continue params["scope_id"] = ct.model_class().objects.get(**query).id From 6e7d5a6f5907136d0e234c05356beb90e042a123 Mon Sep 17 00:00:00 2001 From: Erick Turnquist Date: Thu, 15 Apr 2021 12:18:00 -0400 Subject: [PATCH 17/44] Fix quoting of exec argument in the entrypoint script --- docker/docker-entrypoint.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index c795d6a..c39453d 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -68,6 +68,4 @@ echo "βœ… Initialisation is done." # Launch whatever is passed by docker # (i.e. the RUN instruction in the Dockerfile) -# -# shellcheck disable=SC2068 -exec $@ +exec "$@" From d5c92e9a7d6b762dc7f35b2009a14814b9b2df40 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Fri, 16 Apr 2021 20:27:33 +0200 Subject: [PATCH 18/44] Preparation for 1.2.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9084fa2..26aaba0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.0 +1.2.0 From a89d2e035c90a542e523e0f967794f9c036f9a9d Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Sat, 17 Apr 2021 10:16:40 +0200 Subject: [PATCH 19/44] Don't publish Netbox on random port --- docker-compose.override.yml.example | 5 +++++ docker-compose.yml | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 docker-compose.override.yml.example diff --git a/docker-compose.override.yml.example b/docker-compose.override.yml.example new file mode 100644 index 0000000..f08d6c0 --- /dev/null +++ b/docker-compose.override.yml.example @@ -0,0 +1,5 @@ +version: '3.4' +services: + netbox: + ports: + - 8000:8080 diff --git a/docker-compose.yml b/docker-compose.yml index 4b0fda3..7bec177 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,6 @@ services: - ./reports:/etc/netbox/reports:z,ro - ./scripts:/etc/netbox/scripts:z,ro - netbox-media-files:/opt/netbox/netbox/media:z - ports: - - "8080" netbox-worker: <<: *netbox depends_on: From 53d759e2639a27c658027d7f20b32543036f8687 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 19 Apr 2021 13:13:02 +0000 Subject: [PATCH 20/44] Update dependency django-auth-ldap to v2.4.0 --- requirements-container.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-container.txt b/requirements-container.txt index a4b538a..450c322 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,4 +1,4 @@ napalm==3.2.0 ruamel.yaml==0.17.4 -django-auth-ldap==2.3.0 +django-auth-ldap==2.4.0 django-storages[azure,boto3,dropbox,google,libcloud,sftp]==1.11.1 From 222ede2c4bd4754db93c4c7329a7d5a9924361db Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 03:35:57 -0400 Subject: [PATCH 21/44] enahance ldap extra.py with more examples --- configuration/ldap/extra.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/configuration/ldap/extra.py b/configuration/ldap/extra.py index 2edae86..60a80eb 100644 --- a/configuration/ldap/extra.py +++ b/configuration/ldap/extra.py @@ -1,8 +1,28 @@ #### ## This file contains extra configuration options that can't be configured ## directly through environment variables. +## All vairables set here overwrite any existing found in ldap_config.py #### -# import ldap +# # This Python script inherits all the imports from ldap_config.py +# from django_auth_ldap.config import LDAPGroupQuery # Imported since not in ldap_config.py -# AUTH_LDAP_MIRROR_GROUPS = ["netbox-group-1", "netbox-group-2"] +# # Sets a base requirement of membetship to netbox-user-ro, netbox-user-rw, or netbox-user-admin. +# AUTH_LDAP_REQUIRE_GROUP = ( +# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com") +# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com") +# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com") +# ) + +# # Sets LDAP Flag groups variables with example. +# AUTH_LDAP_USER_FLAGS_BY_GROUP = { +# "is_staff": ( +# LDAPGroupQuery("cn=netbox-user-ro,ou=groups,dc=example,dc=com") +# | LDAPGroupQuery("cn=netbox-user-rw,ou=groups,dc=example,dc=com") +# | LDAPGroupQuery("cn=netbox-user-admin,ou=groups,dc=example,dc=com") +# ), +# "is_superuser": "cn=netbox-user-admin,ou=groups,dc=example,dc=com", +# } + +# # Sets LDAP Mirror groups variables with example groups +# AUTH_LDAP_MIRROR_groups = ["netbox-user-ro", "netbox-user-rw", "netbox-user-admin"] From 6f4d025cb7a859c294c2d4b75f8b4680f3c99c40 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 03:38:20 -0400 Subject: [PATCH 22/44] backed out ldap_config changes --- configuration/ldap/ldap_config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configuration/ldap/ldap_config.py b/configuration/ldap/ldap_config.py index f316ac0..3071b45 100644 --- a/configuration/ldap/ldap_config.py +++ b/configuration/ldap/ldap_config.py @@ -77,8 +77,7 @@ if AUTH_LDAP_REQUIRE_GROUP is not None: # For more granular permissions, we can map LDAP groups to Django groups. AUTH_LDAP_FIND_GROUP_PERMS = environ.get('AUTH_LDAP_FIND_GROUP_PERMS', 'True').lower() == 'true' -if environ.get('AUTH_LDAP_MIRROR_GROUPS') is not None: - AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true' +AUTH_LDAP_MIRROR_GROUPS = environ.get('AUTH_LDAP_MIRROR_GROUPS', '').lower() == 'true' # Cache groups for one hour to reduce LDAP traffic AUTH_LDAP_CACHE_TIMEOUT = int(environ.get('AUTH_LDAP_CACHE_TIMEOUT', 3600)) From eb5cc88b25f7ee4bd7c2faa149f0c9664413e56d Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 07:46:29 -0400 Subject: [PATCH 23/44] Add expample plugin configuration --- .gitignore | 3 ++- configuration/plugins.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 configuration/plugins.py diff --git a/.gitignore b/.gitignore index 04dcc7e..4a44771 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ configuration/* !configuration/configuration.py !configuration/extra.py configuration/ldap/* -!configuration/ldap/ldap_config.py !configuration/ldap/extra.py +!configuration/ldap/ldap_config.py +!configuration/plugins.py prometheus.yml super-linter.log diff --git a/configuration/plugins.py b/configuration/plugins.py new file mode 100644 index 0000000..c11529f --- /dev/null +++ b/configuration/plugins.py @@ -0,0 +1,10 @@ +# Add your plugins and plugin settings here. +# Of course uncomment this file out. + +# PLUGINS = ["netbox_onboarding"] + +# PLUGINS_CONFIG = { +# "netbox_onboarding": { +# ADD YOUR SETTINGS HERE +# } +# } From 8176ef849948e140f4ca2a256703009a8959c24c Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 07:46:39 -0400 Subject: [PATCH 24/44] Add expample logging configuration --- .gitignore | 1 + configuration/logging.py | 53 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 configuration/logging.py diff --git a/.gitignore b/.gitignore index 4a44771..9a5e13a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ configuration/* configuration/ldap/* !configuration/ldap/extra.py !configuration/ldap/ldap_config.py +!configuration/logging.py !configuration/plugins.py prometheus.yml super-linter.log diff --git a/configuration/logging.py b/configuration/logging.py new file mode 100644 index 0000000..ad6c03f --- /dev/null +++ b/configuration/logging.py @@ -0,0 +1,53 @@ +from os import environ + +# Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. +LOGLEVEL = environ.get('LOGLEVEL', 'INFO') + +LOGGING = { + + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', + 'style': '{', + }, + 'simple': { + 'format': '{levelname} {message}', + 'style': '{', + }, + }, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse', + }, + }, + 'handlers': { + 'console': { + 'level': LOGLEVEL, + 'filters': ['require_debug_false'], + 'class': 'logging.StreamHandler', + 'formatter': 'simple' + }, + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + 'filters': ['require_debug_false'] + } + }, + 'loggers': { + 'django': { + 'handlers': ['console'], + 'propagate': True, + }, + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': False, + }, + 'django_auth_ldap': { + 'handlers': ['console',], + 'level': LOGLEVEL, + } + } +} From b69a97d2cafe46f4034e329aa7e1822d5896b168 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 07:48:41 -0400 Subject: [PATCH 25/44] add LOGLEVEL into netbox.env --- env/netbox.env | 1 + 1 file changed, 1 insertion(+) diff --git a/env/netbox.env b/env/netbox.env index 1f6f896..882a6db 100644 --- a/env/netbox.env +++ b/env/netbox.env @@ -14,6 +14,7 @@ EMAIL_USERNAME=netbox # EMAIL_USE_SSL and EMAIL_USE_TLS are mutually exclusive, i.e. they can't both be `true`! EMAIL_USE_SSL=false EMAIL_USE_TLS=false +LOGLEVEL=INFO MAX_PAGE_SIZE=1000 MEDIA_ROOT=/opt/netbox/netbox/media METRICS_ENABLED=false From 9fab9a3434979468e1a4492df96e0ee94cd099f5 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 07:52:08 -0400 Subject: [PATCH 26/44] mention plugin wiki page in plugins.py comment --- configuration/plugins.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configuration/plugins.py b/configuration/plugins.py index c11529f..5cf1287 100644 --- a/configuration/plugins.py +++ b/configuration/plugins.py @@ -1,6 +1,9 @@ # Add your plugins and plugin settings here. # Of course uncomment this file out. +# To learn how to build images with your required plugins +# See https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins + # PLUGINS = ["netbox_onboarding"] # PLUGINS_CONFIG = { From 69dd87689c5db113cc83fc72f90bcf38c48e7a05 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 07:55:12 -0400 Subject: [PATCH 27/44] switch plugin example to netbox_bgp --- configuration/plugins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration/plugins.py b/configuration/plugins.py index 5cf1287..c0b1a1f 100644 --- a/configuration/plugins.py +++ b/configuration/plugins.py @@ -4,10 +4,10 @@ # To learn how to build images with your required plugins # See https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins -# PLUGINS = ["netbox_onboarding"] +# PLUGINS = ["netbox_bgp"] # PLUGINS_CONFIG = { -# "netbox_onboarding": { +# "netbox_bgp": { # ADD YOUR SETTINGS HERE # } # } From 5d4ecb7f9e1de18d201afb3969f4499a5639168b Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 17:47:49 -0400 Subject: [PATCH 28/44] user, group, & permissions fix --- initializers/groups.yml | 38 +++------------- initializers/object_permissions.yml | 22 ++++++++++ initializers/users.yml | 37 ++++++---------- startup_scripts/000_users.py | 5 +-- startup_scripts/010_groups.py | 22 ++++++---- startup_scripts/015_object_permissions.py | 44 +++++++++++++++++++ .../startup_script_utils/permissions.py | 22 ---------- 7 files changed, 100 insertions(+), 90 deletions(-) create mode 100644 initializers/object_permissions.yml create mode 100644 startup_scripts/015_object_permissions.py delete mode 100644 startup_scripts/startup_script_utils/permissions.py diff --git a/initializers/groups.yml b/initializers/groups.yml index b91ef39..45f4703 100644 --- a/initializers/groups.yml +++ b/initializers/groups.yml @@ -1,35 +1,9 @@ -## To list all permissions, run: -## -## docker-compose run --rm --entrypoint /bin/bash netbox -## $ ./manage.py migrate -## $ ./manage.py shell -## > from django.contrib.auth.models import Permission -## > print('\n'.join([p.codename for p in Permission.objects.all()])) -## -## Permission lists support wildcards. See the examples below. -## -## Examples: - -# applications: +# - name: applications # users: -# - technical_user -# readers: +# - technical_user +# - name: readers # users: -# - reader -# writers: +# - reader +# - name: writers # users: -# - writer -# permissions: -# - delete_device -# - delete_virtualmachine -# - add_* -# - change_* -# vm_managers: -# permissions: -# - '*_virtualmachine' -# device_managers: -# permissions: -# - '*device*' -# creators: -# permissions: -# - add_* +# - writer diff --git a/initializers/object_permissions.yml b/initializers/object_permissions.yml new file mode 100644 index 0000000..5daa981 --- /dev/null +++ b/initializers/object_permissions.yml @@ -0,0 +1,22 @@ +#- name: all.ro +# description: 'Read Only for All Objects' +# enabled: true +# # object_types: all +# groups: +# - applications +# - readers +# actions: +# - view +#- name: all.rw +# description: 'Read/Write for All Objects' +# enabled: true +# # object_types: all +# groups: +# - writers +# users: +# - jdoe +# actions: +# - add +# - change +# - delete +# - view diff --git a/initializers/users.yml b/initializers/users.yml index 2aea62e..5e0168d 100644 --- a/initializers/users.yml +++ b/initializers/users.yml @@ -1,23 +1,14 @@ -## To list all permissions, run: -## -## docker-compose run --rm --entrypoint /bin/bash netbox -## $ ./manage.py migrate -## $ ./manage.py shell -## > from django.contrib.auth.models import Permission -## > print('\n'.join([p.codename for p in Permission.objects.all()])) -## -## Permission lists support wildcards. See the examples below. -## -## Examples: - -# technical_user: -# api_token: 0123456789technicaluser789abcdef01234567 # must be looooong! -# reader: -# password: reader -# writer: -# password: writer -# permissions: -# - delete_device -# - delete_virtualmachine -# - add_* -# - change_* +#- username: technical_user +# api_token: 0123456789technicaluser789abcdef01234567 # must be looooong! +#- username: reader +# password: reader +#- username: writer +# password: writer +#- username: jdoe +# first_name: John +# last_name: Doe +# api_token: 0123456789jdoe789abcdef01234567jdoe +# is_active: True +# is_superuser: False +# is_staff: False +# email: john.doe@example.com diff --git a/startup_scripts/000_users.py b/startup_scripts/000_users.py index 66b8519..1435d81 100644 --- a/startup_scripts/000_users.py +++ b/startup_scripts/000_users.py @@ -1,7 +1,7 @@ import sys from django.contrib.auth.models import User -from startup_script_utils import load_yaml, set_permissions +from startup_script_utils import load_yaml from users.models import Token users = load_yaml("/opt/netbox/initializers/users.yml") @@ -19,6 +19,3 @@ for username, user_details in users.items(): if user_details.get("api_token", 0): Token.objects.create(user=user, key=user_details["api_token"]) - - yaml_permissions = user_details.get("permissions", []) - set_permissions(user.user_permissions, yaml_permissions) diff --git a/startup_scripts/010_groups.py b/startup_scripts/010_groups.py index 6726868..a17d004 100644 --- a/startup_scripts/010_groups.py +++ b/startup_scripts/010_groups.py @@ -1,23 +1,27 @@ import sys -from django.contrib.auth.models import Group, User -from startup_script_utils import load_yaml, set_permissions +from users.models import AdminGroup, AdminUser +from startup_script_utils import load_yaml groups = load_yaml("/opt/netbox/initializers/groups.yml") if groups is None: sys.exit() -for groupname, group_details in groups.items(): - group, created = Group.objects.get_or_create(name=groupname) +for params in groups: + groupname=params['name'] + + group, created = AdminGroup.objects.get_or_create( + name=groupname + ) if created: print("πŸ‘₯ Created group", groupname) - for username in group_details.get("users", []): - user = User.objects.get(username=username) + for username in params.get("users", []): + user = AdminUser.objects.get(username=username) if user: - user.groups.add(group) + group.user_set.add(user) + print(" πŸ‘€ Assigned user %s to group %s" % (username, AdminGroup.name)) - yaml_permissions = group_details.get("permissions", []) - set_permissions(group.permissions, yaml_permissions) + group.save() diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py new file mode 100644 index 0000000..f2de75c --- /dev/null +++ b/startup_scripts/015_object_permissions.py @@ -0,0 +1,44 @@ +import sys + +from users.models import ObjectPermission, AdminGroup, AdminUser +from startup_script_utils import load_yaml +from django.contrib.contenttypes.models import ContentType + +object_permissions = load_yaml("/opt/netbox/initializers/object_permissions.yml") + +if object_permissions is None: + sys.exit() + + +for params in object_permissions: + + object_permission, created = ObjectPermission.objects.get_or_create( + name=params['name'], + description=params['description'], + enabled=params['enabled'], + actions=params['actions'] + ) + +# Need to try to pass a list of model_name and app_label for more than just the current all objects. + #object_types = ContentType.objects.filter(app_label__in=params.pop("object_types")) + #object_permission.object_types.set(ContentType.objects.filter(app_label__in=params.pop("object_types"))) + object_permission.object_types.set(ContentType.objects.all()) + object_permission.save() + + print("πŸ”“ Created object permission", object_permission.name) + + for groupname in params.get("groups", []): + group = AdminGroup.objects.get(name=groupname) + + if group: + object_permission.groups.add(group) + print(" πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name)) + + for username in params.get("users", []): + user = AdminUser.objects.get(username=username) + + if user: + object_permission.users.add(user) + print(" πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name)) + + object_permission.save() diff --git a/startup_scripts/startup_script_utils/permissions.py b/startup_scripts/startup_script_utils/permissions.py deleted file mode 100644 index 021b0b5..0000000 --- a/startup_scripts/startup_script_utils/permissions.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.contrib.auth.models import Permission - - -def set_permissions(subject, permission_filters): - if subject is None or permission_filters is None: - return - subject.clear() - for permission_filter in permission_filters: - if "*" in permission_filter: - permission_filter_regex = "^" + permission_filter.replace("*", ".*") + "$" - permissions = Permission.objects.filter(codename__iregex=permission_filter_regex) - print( - " ⚿ Granting", - permissions.count(), - "permissions matching '" + permission_filter + "'", - ) - else: - permissions = Permission.objects.filter(codename=permission_filter) - print(" ⚿ Granting permission", permission_filter) - - for permission in permissions: - subject.add(permission) From a7a5d1363763987d8c7bdcba5c3c13275593f1ba Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Tue, 20 Apr 2021 18:05:47 -0400 Subject: [PATCH 29/44] updated given linting feedback --- startup_scripts/010_groups.py | 6 ++---- startup_scripts/015_object_permissions.py | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/startup_scripts/010_groups.py b/startup_scripts/010_groups.py index a17d004..19bc2da 100644 --- a/startup_scripts/010_groups.py +++ b/startup_scripts/010_groups.py @@ -8,11 +8,9 @@ if groups is None: sys.exit() for params in groups: - groupname=params['name'] + groupname = params["name"] - group, created = AdminGroup.objects.get_or_create( - name=groupname - ) + group, created = AdminGroup.objects.get_or_create(name=groupname) if created: print("πŸ‘₯ Created group", groupname) diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index f2de75c..02d5554 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -13,15 +13,15 @@ if object_permissions is None: for params in object_permissions: object_permission, created = ObjectPermission.objects.get_or_create( - name=params['name'], - description=params['description'], - enabled=params['enabled'], - actions=params['actions'] + name=params["name"], + description=params["description"], + enabled=params["enabled"], + actions=params["actions"], ) -# Need to try to pass a list of model_name and app_label for more than just the current all objects. - #object_types = ContentType.objects.filter(app_label__in=params.pop("object_types")) - #object_permission.object_types.set(ContentType.objects.filter(app_label__in=params.pop("object_types"))) + # Need to try to pass a list of model_name and app_label for more than the current ALL + # object_types = ContentType.objects.filter(app_label__in=params.pop("object_types")) + # object_permission.object_types.set(ContentType.objects.filter(app_label__in=params.pop("object_types"))) object_permission.object_types.set(ContentType.objects.all()) object_permission.save() @@ -32,13 +32,17 @@ for params in object_permissions: if group: object_permission.groups.add(group) - print(" πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name)) + print( + " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name) + ) for username in params.get("users", []): user = AdminUser.objects.get(username=username) if user: object_permission.users.add(user) - print(" πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name)) + print( + " πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name) + ) object_permission.save() From b1bcfcbc4ef5963a584b7d784f70a08af6bc92c1 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 21 Apr 2021 08:27:20 -0400 Subject: [PATCH 30/44] fix isort on groups & permissions scripts --- startup_scripts/010_groups.py | 2 +- startup_scripts/015_object_permissions.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/startup_scripts/010_groups.py b/startup_scripts/010_groups.py index 19bc2da..2abd1ba 100644 --- a/startup_scripts/010_groups.py +++ b/startup_scripts/010_groups.py @@ -1,7 +1,7 @@ import sys -from users.models import AdminGroup, AdminUser from startup_script_utils import load_yaml +from users.models import AdminGroup, AdminUser groups = load_yaml("/opt/netbox/initializers/groups.yml") if groups is None: diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index 02d5554..5b41e52 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -1,8 +1,8 @@ import sys -from users.models import ObjectPermission, AdminGroup, AdminUser -from startup_script_utils import load_yaml from django.contrib.contenttypes.models import ContentType +from startup_script_utils import load_yaml +from users.models import AdminGroup, AdminUser, ObjectPermission object_permissions = load_yaml("/opt/netbox/initializers/object_permissions.yml") From 744ed91e2a7a01d98d2b2ca928412d0938408e9e Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 21 Apr 2021 12:33:35 -0400 Subject: [PATCH 31/44] permissions script cleanup --- startup_scripts/startup_script_utils/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/startup_scripts/startup_script_utils/__init__.py b/startup_scripts/startup_script_utils/__init__.py index 2f92370..290b87b 100644 --- a/startup_scripts/startup_script_utils/__init__.py +++ b/startup_scripts/startup_script_utils/__init__.py @@ -1,3 +1,2 @@ from .custom_fields import pop_custom_fields, set_custom_fields_values from .load_yaml import load_yaml -from .permissions import set_permissions From 71d8ac10ac3ff7c3ca52d3f38dd50e79abd3e877 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Wed, 21 Apr 2021 12:59:30 -0400 Subject: [PATCH 32/44] correct issues with users.yml spacing --- initializers/users.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/initializers/users.yml b/initializers/users.yml index 5e0168d..ccf106f 100644 --- a/initializers/users.yml +++ b/initializers/users.yml @@ -1,14 +1,14 @@ -#- username: technical_user -# api_token: 0123456789technicaluser789abcdef01234567 # must be looooong! -#- username: reader -# password: reader -#- username: writer -# password: writer -#- username: jdoe -# first_name: John -# last_name: Doe -# api_token: 0123456789jdoe789abcdef01234567jdoe -# is_active: True -# is_superuser: False -# is_staff: False -# email: john.doe@example.com +# - username: technical_user +# api_token: 0123456789technicaluser789abcdef01234567 # must be looooong! +# - username: reader +# password: reader +# - username: writer +# password: writer +# - username: jdoe +# first_name: John +# last_name: Doe +# api_token: 0123456789jdoe789abcdef01234567jdoe +# is_active: True +# is_superuser: False +# is_staff: False +# email: john.doe@example.com From 45889c3811bef9ab0bcceea69515891373c82f5b Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Fri, 23 Apr 2021 22:38:38 -0400 Subject: [PATCH 33/44] commented out the logging --- configuration/logging.py | 107 ++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/configuration/logging.py b/configuration/logging.py index ad6c03f..ec05c88 100644 --- a/configuration/logging.py +++ b/configuration/logging.py @@ -1,53 +1,54 @@ -from os import environ - -# Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. -LOGLEVEL = environ.get('LOGLEVEL', 'INFO') - -LOGGING = { - - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'verbose': { - 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', - 'style': '{', - }, - 'simple': { - 'format': '{levelname} {message}', - 'style': '{', - }, - }, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse', - }, - }, - 'handlers': { - 'console': { - 'level': LOGLEVEL, - 'filters': ['require_debug_false'], - 'class': 'logging.StreamHandler', - 'formatter': 'simple' - }, - 'mail_admins': { - 'level': 'ERROR', - 'class': 'django.utils.log.AdminEmailHandler', - 'filters': ['require_debug_false'] - } - }, - 'loggers': { - 'django': { - 'handlers': ['console'], - 'propagate': True, - }, - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': False, - }, - 'django_auth_ldap': { - 'handlers': ['console',], - 'level': LOGLEVEL, - } - } -} +##Remove first comment(#) on each line to implement this working logging example. +#from os import environ +# +## Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. +#LOGLEVEL = environ.get('LOGLEVEL', 'INFO') +# +#LOGGING = { +# +# 'version': 1, +# 'disable_existing_loggers': False, +# 'formatters': { +# 'verbose': { +# 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', +# 'style': '{', +# }, +# 'simple': { +# 'format': '{levelname} {message}', +# 'style': '{', +# }, +# }, +# 'filters': { +# 'require_debug_false': { +# '()': 'django.utils.log.RequireDebugFalse', +# }, +# }, +# 'handlers': { +# 'console': { +# 'level': LOGLEVEL, +# 'filters': ['require_debug_false'], +# 'class': 'logging.StreamHandler', +# 'formatter': 'simple' +# }, +# 'mail_admins': { +# 'level': 'ERROR', +# 'class': 'django.utils.log.AdminEmailHandler', +# 'filters': ['require_debug_false'] +# } +# }, +# 'loggers': { +# 'django': { +# 'handlers': ['console'], +# 'propagate': True, +# }, +# 'django.request': { +# 'handlers': ['mail_admins'], +# 'level': 'ERROR', +# 'propagate': False, +# }, +# 'django_auth_ldap': { +# 'handlers': ['console',], +# 'level': LOGLEVEL, +# } +# } +#} From a1e0c52825870a0c47ac0f7bbf83a62a7dfb87c3 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sat, 24 Apr 2021 10:41:06 -0400 Subject: [PATCH 34/44] revert startup scripts to use key for object name --- initializers/groups.yml | 6 +++--- initializers/users.yml | 8 ++++---- startup_scripts/010_groups.py | 6 ++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/initializers/groups.yml b/initializers/groups.yml index 45f4703..15213a6 100644 --- a/initializers/groups.yml +++ b/initializers/groups.yml @@ -1,9 +1,9 @@ -# - name: applications +# applications: # users: # - technical_user -# - name: readers +# readers: # users: # - reader -# - name: writers +# writers: # users: # - writer diff --git a/initializers/users.yml b/initializers/users.yml index ccf106f..c163d50 100644 --- a/initializers/users.yml +++ b/initializers/users.yml @@ -1,10 +1,10 @@ -# - username: technical_user +# technical_user: # api_token: 0123456789technicaluser789abcdef01234567 # must be looooong! -# - username: reader +# reader: # password: reader -# - username: writer +# writer: # password: writer -# - username: jdoe +# jdoe: # first_name: John # last_name: Doe # api_token: 0123456789jdoe789abcdef01234567jdoe diff --git a/startup_scripts/010_groups.py b/startup_scripts/010_groups.py index 2abd1ba..39aca53 100644 --- a/startup_scripts/010_groups.py +++ b/startup_scripts/010_groups.py @@ -7,15 +7,13 @@ groups = load_yaml("/opt/netbox/initializers/groups.yml") if groups is None: sys.exit() -for params in groups: - groupname = params["name"] - +for groupname, group_details in groups.items(): group, created = AdminGroup.objects.get_or_create(name=groupname) if created: print("πŸ‘₯ Created group", groupname) - for username in params.get("users", []): + for username in group_details.get("users", []): user = AdminUser.objects.get(username=username) if user: From ff0bc9757a9f7bfc5d3b34700801ebef8f287f81 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sat, 24 Apr 2021 10:57:15 -0400 Subject: [PATCH 35/44] correct ldap example var name case --- configuration/ldap/extra.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/ldap/extra.py b/configuration/ldap/extra.py index 60a80eb..4505197 100644 --- a/configuration/ldap/extra.py +++ b/configuration/ldap/extra.py @@ -25,4 +25,4 @@ # } # # Sets LDAP Mirror groups variables with example groups -# AUTH_LDAP_MIRROR_groups = ["netbox-user-ro", "netbox-user-rw", "netbox-user-admin"] +# AUTH_LDAP_MIRROR_GROUPS = ["netbox-user-ro", "netbox-user-rw", "netbox-user-admin"] From 4e31218ce64d3bf36ed3c8f6f16c69ad48373f23 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sun, 25 Apr 2021 11:15:46 -0400 Subject: [PATCH 36/44] update object permission conditionals --- startup_scripts/015_object_permissions.py | 46 ++++++++++++----------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index 5b41e52..5d9cede 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -10,39 +10,41 @@ if object_permissions is None: sys.exit() -for params in object_permissions: +for permission_name, permission_details in object_permissions.items(): object_permission, created = ObjectPermission.objects.get_or_create( - name=params["name"], - description=params["description"], - enabled=params["enabled"], - actions=params["actions"], + name=permission_name, + description=permission_details["description"], + enabled=permission_details["enabled"], + actions=permission_details["actions"], ) # Need to try to pass a list of model_name and app_label for more than the current ALL - # object_types = ContentType.objects.filter(app_label__in=params.pop("object_types")) - # object_permission.object_types.set(ContentType.objects.filter(app_label__in=params.pop("object_types"))) + # object_types = ContentType.objects.filter(app_label__in=permission_details["object_types"]) + # object_permission.object_types.set(ContentType.objects.filter(app_label__in=permission_details"object_types"])) object_permission.object_types.set(ContentType.objects.all()) object_permission.save() print("πŸ”“ Created object permission", object_permission.name) + + if permission_details.get("groups", 0): + for groupname in permission_details["groups"]: + group = AdminGroup.objects.get(name=groupname) - for groupname in params.get("groups", []): - group = AdminGroup.objects.get(name=groupname) + if group: + object_permission.groups.add(group) + print( + " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name) + ) - if group: - object_permission.groups.add(group) - print( - " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name) - ) + if permission_details.get("users", 0): + for username in permission_details["users"]: + user = AdminUser.objects.get(username=username) - for username in params.get("users", []): - user = AdminUser.objects.get(username=username) - - if user: - object_permission.users.add(user) - print( - " πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name) - ) + if user: + object_permission.users.add(user) + print( + " πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name) + ) object_permission.save() From 528bc17eb84bcabd7dc11cafabfbea9d2271267f Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sun, 25 Apr 2021 11:59:13 -0400 Subject: [PATCH 37/44] correct flake8 in object_permissions.py --- startup_scripts/015_object_permissions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index 5d9cede..a4fc4a9 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -14,7 +14,7 @@ for permission_name, permission_details in object_permissions.items(): object_permission, created = ObjectPermission.objects.get_or_create( name=permission_name, - description=permission_details["description"], + description=permission_details["description"], enabled=permission_details["enabled"], actions=permission_details["actions"], ) @@ -26,7 +26,7 @@ for permission_name, permission_details in object_permissions.items(): object_permission.save() print("πŸ”“ Created object permission", object_permission.name) - + if permission_details.get("groups", 0): for groupname in permission_details["groups"]: group = AdminGroup.objects.get(name=groupname) @@ -34,7 +34,7 @@ for permission_name, permission_details in object_permissions.items(): if group: object_permission.groups.add(group) print( - " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, object_permission.name) + " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, groupname) ) if permission_details.get("users", 0): @@ -44,7 +44,7 @@ for permission_name, permission_details in object_permissions.items(): if user: object_permission.users.add(user) print( - " πŸ‘€ Assigned user %s object permission of %s" % (username, object_permission.name) + " πŸ‘€ Assigned user %s object permission of %s" % (username, groupname) ) object_permission.save() From 12401f2a3f04087400645a5878d50a84b77b11a2 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sun, 25 Apr 2021 12:13:27 -0400 Subject: [PATCH 38/44] correct black formatting for object_permissions.py --- startup_scripts/015_object_permissions.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index a4fc4a9..af9f844 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -33,9 +33,7 @@ for permission_name, permission_details in object_permissions.items(): if group: object_permission.groups.add(group) - print( - " πŸ‘₯ Assigned group %s object permission of %s" % (groupname, groupname) - ) + print(" πŸ‘₯ Assigned group %s object permission of %s" % (groupname, groupname)) if permission_details.get("users", 0): for username in permission_details["users"]: @@ -43,8 +41,6 @@ for permission_name, permission_details in object_permissions.items(): if user: object_permission.users.add(user) - print( - " πŸ‘€ Assigned user %s object permission of %s" % (username, groupname) - ) + print(" πŸ‘€ Assigned user %s object permission of %s" % (username, groupname)) object_permission.save() From 474ca9e78f3db98fc945f46291c75db3fc5e9b4d Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sun, 25 Apr 2021 16:31:50 -0400 Subject: [PATCH 39/44] fully working object permissions --- initializers/object_permissions.yml | 70 ++++++++++++++++------- startup_scripts/015_object_permissions.py | 24 ++++++-- 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/initializers/object_permissions.yml b/initializers/object_permissions.yml index 5daa981..332011f 100644 --- a/initializers/object_permissions.yml +++ b/initializers/object_permissions.yml @@ -1,22 +1,48 @@ -#- name: all.ro -# description: 'Read Only for All Objects' -# enabled: true -# # object_types: all -# groups: -# - applications -# - readers -# actions: -# - view -#- name: all.rw -# description: 'Read/Write for All Objects' -# enabled: true -# # object_types: all -# groups: -# - writers -# users: -# - jdoe -# actions: -# - add -# - change -# - delete -# - view +# 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 diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index af9f844..c17ce84 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -19,11 +19,25 @@ for permission_name, permission_details in object_permissions.items(): actions=permission_details["actions"], ) - # Need to try to pass a list of model_name and app_label for more than the current ALL - # object_types = ContentType.objects.filter(app_label__in=permission_details["object_types"]) - # object_permission.object_types.set(ContentType.objects.filter(app_label__in=permission_details"object_types"])) - object_permission.object_types.set(ContentType.objects.all()) - object_permission.save() + if permission_details.get("object_types", 0): + object_types = permission_details["object_types"] + + if object_types == "all": + object_permission.object_types.set(ContentType.objects.all()) + + else: + for app_label, models in object_types.items(): + if models == "all": + app_models = ContentType.objects.filter(app_label=app_label) + + for app_model in app_models: + object_permission.object_types.add(app_model.id) + else: + # There is + for model in models: + object_permission.object_types.add( + ContentType.objects.get(app_label=app_label, model=model) + ) print("πŸ”“ Created object permission", object_permission.name) From 96545135cba17169f20aafe56a4278f1216aaf2d Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Sun, 25 Apr 2021 16:38:03 -0400 Subject: [PATCH 40/44] remove example evn var for logging --- configuration/logging.py | 3 ++- env/netbox.env | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration/logging.py b/configuration/logging.py index ec05c88..6be398f 100644 --- a/configuration/logging.py +++ b/configuration/logging.py @@ -1,4 +1,5 @@ -##Remove first comment(#) on each line to implement this working logging example. +## 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 # ## Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. diff --git a/env/netbox.env b/env/netbox.env index 882a6db..1f6f896 100644 --- a/env/netbox.env +++ b/env/netbox.env @@ -14,7 +14,6 @@ EMAIL_USERNAME=netbox # EMAIL_USE_SSL and EMAIL_USE_TLS are mutually exclusive, i.e. they can't both be `true`! EMAIL_USE_SSL=false EMAIL_USE_TLS=false -LOGLEVEL=INFO MAX_PAGE_SIZE=1000 MEDIA_ROOT=/opt/netbox/netbox/media METRICS_ENABLED=false From f924e76adfe597a307785124d86147f1bee436b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ma=CC=88der?= Date: Mon, 26 Apr 2021 08:55:22 +0200 Subject: [PATCH 41/44] Formatting --- configuration/logging.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/configuration/logging.py b/configuration/logging.py index 6be398f..d786768 100644 --- a/configuration/logging.py +++ b/configuration/logging.py @@ -1,12 +1,12 @@ -## 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 -# -## Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. -#LOGLEVEL = environ.get('LOGLEVEL', 'INFO') -# -#LOGGING = { -# +# # 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 + +# # Set LOGLEVEL in netbox.env or docker-compose.overide.yml to override a logging level of INFO. +# LOGLEVEL = environ.get('LOGLEVEL', 'INFO') + +# LOGGING = { + # 'version': 1, # 'disable_existing_loggers': False, # 'formatters': { @@ -52,4 +52,4 @@ # 'level': LOGLEVEL, # } # } -#} +# } From 5b34df147160c5f6a2d1ba72f99a841c3c8dbd80 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Sat, 24 Apr 2021 10:58:15 +0200 Subject: [PATCH 42/44] Build feature branch The branch for the next version of Netbox is now called "feature". --- .github/workflows/push.yml | 2 +- .github/workflows/release.yml | 2 +- build-next.sh | 39 ----------------------------------- 3 files changed, 2 insertions(+), 41 deletions(-) delete mode 100755 build-next.sh diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 3ea6214..3293aff 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -42,7 +42,7 @@ jobs: build_cmd: - ./build-latest.sh - PRERELEASE=true ./build-latest.sh - - ./build-next.sh + - ./build.sh feature - ./build.sh develop docker_from: - '' # use the default of the build script diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f0e317..eb47cfe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: build_cmd: - ./build-latest.sh - PRERELEASE=true ./build-latest.sh - - ./build-next.sh + - ./build.sh feature - ./build.sh develop fail-fast: false runs-on: ubuntu-latest diff --git a/build-next.sh b/build-next.sh deleted file mode 100755 index 88f290b..0000000 --- a/build-next.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# Builds develop, develop-* and master branches of NetBox - -echo "▢️ $0 $*" - -### -# Checking for the presence of GITHUB_OAUTH_CLIENT_ID -# and GITHUB_OAUTH_CLIENT_SECRET -### -if [ -n "${GITHUB_OAUTH_CLIENT_ID}" ] && [ -n "${GITHUB_OAUTH_CLIENT_SECRET}" ]; then - echo "πŸ— Performing authenticated Github API calls." - GITHUB_OAUTH_PARAMS="client_id=${GITHUB_OAUTH_CLIENT_ID}&client_secret=${GITHUB_OAUTH_CLIENT_SECRET}" -else - echo "πŸ•Ά Performing unauthenticated Github API calls. This might result in lower Github rate limits!" - GITHUB_OAUTH_PARAMS="" -fi - -### -# Calling Github to get the all branches -### -ORIGINAL_GITHUB_REPO="${SRC_ORG-netbox-community}/${SRC_REPO-netbox}" -GITHUB_REPO="${GITHUB_REPO-$ORIGINAL_GITHUB_REPO}" -URL_RELEASES="https://api.github.com/repos/${GITHUB_REPO}/branches?${GITHUB_OAUTH_PARAMS}" - -# Composing the JQ commans to extract the most recent version number -JQ_NEXT='map(.name) | .[] | scan("^[^v].+") | match("^(develop-).*") | .string' - -CURL="curl -sS" - -# Querying the Github API to fetch all branches -NEXT=$($CURL "${URL_RELEASES}" | jq -r "$JQ_NEXT") - -if [ -n "$NEXT" ]; then - # shellcheck disable=SC2068 - ./build.sh "${NEXT}" $@ -else - echo "No branch matching 'develop-*' found" - echo "::set-output name=skipped::true" -fi From 8678ad92ce2e2609cb39f69d73d14c2afe40f1ec Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Mon, 26 Apr 2021 09:17:25 -0400 Subject: [PATCH 43/44] update permission user & group lookup as suggested --- startup_scripts/015_object_permissions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/015_object_permissions.py index c17ce84..f19b6ae 100644 --- a/startup_scripts/015_object_permissions.py +++ b/startup_scripts/015_object_permissions.py @@ -43,7 +43,7 @@ for permission_name, permission_details in object_permissions.items(): if permission_details.get("groups", 0): for groupname in permission_details["groups"]: - group = AdminGroup.objects.get(name=groupname) + group = AdminGroup.objects.filter(name=groupname).first() if group: object_permission.groups.add(group) @@ -51,7 +51,7 @@ for permission_name, permission_details in object_permissions.items(): if permission_details.get("users", 0): for username in permission_details["users"]: - user = AdminUser.objects.get(username=username) + user = AdminUser.objects.filter(username=username).first() if user: object_permission.users.add(user) From 1f3d9463f98b37f7f165d0c416c03d054de0f863 Mon Sep 17 00:00:00 2001 From: ryanmerolle Date: Mon, 26 Apr 2021 10:26:10 -0400 Subject: [PATCH 44/44] apply black formating to all startup_scripts --- startup_scripts/280_custom_links.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup_scripts/280_custom_links.py b/startup_scripts/280_custom_links.py index b611763..40144bd 100644 --- a/startup_scripts/280_custom_links.py +++ b/startup_scripts/280_custom_links.py @@ -23,7 +23,7 @@ for link in custom_links: if link["content_type_id"] is None: print( "⚠️ Unable to create Custom Link '{0}': The content_type '{1}' is unknown".format( - link.get('name'), content_type + link.get("name"), content_type ) ) continue