diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 608e6e0..d77ceb5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -46,7 +46,6 @@ jobs: - ./build.sh develop docker_from: - '' # use the default of the build script - - alpine:edge fail-fast: false runs-on: ubuntu-latest name: Builds new NetBox Docker Images diff --git a/Dockerfile b/Dockerfile index 505b888..51cd359 100644 --- a/Dockerfile +++ b/Dockerfile @@ -97,7 +97,7 @@ WORKDIR /opt/netbox/netbox RUN mkdir -p static /opt/unit/state/ /opt/unit/tmp/ \ && chown -R unit:root media /opt/unit/ \ && chmod -R g+w media /opt/unit/ \ - && cd /opt/netbox/ && /opt/netbox/venv/bin/python -m mkdocs build \ + && cd /opt/netbox/ && SECRET_KEY="dummy" /opt/netbox/venv/bin/python -m mkdocs build \ --config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \ && SECRET_KEY="dummy" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input diff --git a/README.md b/README.md index d8aedf4..b76f9cf 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ![Docker Pulls](https://img.shields.io/docker/pulls/netboxcommunity/netbox) [![GitHub license](https://img.shields.io/github/license/netbox-community/netbox-docker)][netbox-docker-license] -[The Github repository](netbox-docker-github) houses the components needed to build NetBox as a container. +[The GitHub repository](netbox-docker-github) houses the components needed to build NetBox as a container. Images are built regularly using the code in that repository and are pushed to [Docker Hub][netbox-dockerhub], [Quay.io][netbox-quayio] and [GitHub Container Registry][netbox-ghcr]. Do you have any questions? @@ -19,7 +19,7 @@ please join [our Slack][netbox-docker-slack] and ask for help in the [`#netbox-d [netbox-docker-microbadger]: https://microbadger.com/images/netboxcommunity/netbox [netbox-dockerhub]: https://hub.docker.com/r/netboxcommunity/netbox/ [netbox-quayio]: https://quay.io/repository/netboxcommunity/netbox -[netbox-ghcr]: https://ghcr.io/netbox-community/netbox/ +[netbox-ghcr]: https://github.com/netbox-community/netbox-docker/pkgs/container/netbox [netbox-docker-github]: https://github.com/netbox-community/netbox-docker/ [netbox-docker-slack]: https://join.slack.com/t/netdev-community/shared_invite/zt-mtts8g0n-Sm6Wutn62q_M4OdsaIycrQ [netbox-docker-slack-channel]: https://netdev-community.slack.com/archives/C01P0GEVBU7 @@ -75,7 +75,7 @@ New container images are built and published automatically every ~24h. You must use _NetBox Docker version_ `a.b.c` to guarantee the compatibility. These images are automatically built from [the `master` branch of NetBox][netbox-master]. * `snapshot-a.b.c`: - These are pre-release builds. + These are prerelease builds. They contain the support files of _NetBox Docker version_ `a.b.c`. You must use _NetBox Docker version_ `a.b.c` to guarantee the compatibility. These images are automatically built from the [`develop` branch of NetBox][netbox-develop]. @@ -106,7 +106,7 @@ Then there is currently one extra tags for each of the above tags: ## Documentation -Please refer [to our wiki on Github][netbox-docker-wiki] for further information on how to use the NetBox Docker image properly. +Please refer [to our wiki on GitHub][netbox-docker-wiki] for further information on how to use the NetBox Docker image properly. The wiki covers advanced topics such as using files for secrets, configuring TLS, deployment to Kubernetes, monitoring and configuring NAPALM and LDAP. Our wiki is a community effort. @@ -116,7 +116,7 @@ Feel free to correct errors, update outdated information or provide additional g ## Getting Help -Feel free to ask questions in our [Github Community][netbox-community] +Feel free to ask questions in our [GitHub Community][netbox-community] or [join our Slack][netbox-docker-slack] and ask [in our channel `#netbox-docker`][netbox-docker-slack-channel], which is free to use and where there are almost always people online that can help you in the Slack channel. diff --git a/VERSION b/VERSION index 26ca594..dc1e644 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.1 +1.6.0 diff --git a/configuration/configuration.py b/configuration/configuration.py index 311d1f0..1db6051 100644 --- a/configuration/configuration.py +++ b/configuration/configuration.py @@ -147,6 +147,9 @@ ENFORCE_GLOBAL_UNIQUE = environ.get('ENFORCE_GLOBAL_UNIQUE', 'False').lower() == # by anonymous users. List models in the form `.`. Add '*' to this list to exempt all models. EXEMPT_VIEW_PERMISSIONS = list(filter(None, environ.get('EXEMPT_VIEW_PERMISSIONS', '').split(' '))) +# Enable GraphQL API. +GRAPHQL_ENABLED = environ.get('GRAPHQL_ENABLED', 'True').lower() == 'true' + # Enable custom logging. Please see the Django documentation for detailed guidance on configuring custom logs: # https://docs.djangoproject.com/en/stable/topics/logging/ LOGGING = {} diff --git a/docker-compose.yml b/docker-compose.yml index 3b68f08..9c6a284 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.4' services: netbox: &netbox - image: netboxcommunity/netbox:${VERSION-v3.1-1.5.1} + image: netboxcommunity/netbox:${VERSION-v3.1-1.6.0} depends_on: - postgres - redis diff --git a/env/netbox.env b/env/netbox.env index 6593cbc..456cac9 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 +GRAPHQL_ENABLED=true HOUSEKEEPING_INTERVAL=86400 MAX_PAGE_SIZE=1000 MEDIA_ROOT=/opt/netbox/netbox/media diff --git a/initializers/asns.yml b/initializers/asns.yml new file mode 100644 index 0000000..f75408b --- /dev/null +++ b/initializers/asns.yml @@ -0,0 +1,7 @@ +# - asn: 1 +# rir: RFC1918 +# tenant: tenant1 +# - asn: 2 +# rir: RFC4193 ULA +# - asn: 3 +# rir: RFC3849 diff --git a/initializers/sites.yml b/initializers/sites.yml index 7ace3aa..700c853 100644 --- a/initializers/sites.yml +++ b/initializers/sites.yml @@ -3,7 +3,6 @@ # region: Downtown # status: active # facility: Amsterdam 1 -# asn: 12345 # custom_field_data: # text_field: Description for AMS1 # - name: AMS 2 @@ -11,7 +10,6 @@ # region: Downtown # status: active # facility: Amsterdam 2 -# asn: 54321 # custom_field_data: # text_field: Description for AMS2 # - name: AMS 3 @@ -19,7 +17,6 @@ # region: Suburbs # status: active # facility: Amsterdam 3 -# asn: 67890 # tenant: tenant1 # custom_field_data: # text_field: Description for AMS3 @@ -28,7 +25,6 @@ # region: Singapore # status: active # facility: Singapore 1 -# asn: 09876 # tenant: tenant2 # custom_field_data: # text_field: Description for SING1 diff --git a/requirements-container.txt b/requirements-container.txt index f47f232..2542395 100644 --- a/requirements-container.txt +++ b/requirements-container.txt @@ -1,5 +1,6 @@ -napalm==3.3.1 -ruamel.yaml==0.17.17 -django-auth-ldap==3.0.0 -google-crc32c==1.3.0 +django-auth-ldap==4.0.0 django-storages[azure,boto3,dropbox,google,libcloud,sftp]==1.12.3 +google-crc32c==1.3.0 +napalm==3.3.1 +ruamel.yaml==0.17.21 +tzdata==2021.5 diff --git a/startup_scripts/015_object_permissions.py b/startup_scripts/020_object_permissions.py similarity index 100% rename from startup_scripts/015_object_permissions.py rename to startup_scripts/020_object_permissions.py diff --git a/startup_scripts/020_custom_fields.py b/startup_scripts/030_custom_fields.py similarity index 100% rename from startup_scripts/020_custom_fields.py rename to startup_scripts/030_custom_fields.py diff --git a/startup_scripts/280_custom_links.py b/startup_scripts/040_custom_links.py similarity index 100% rename from startup_scripts/280_custom_links.py rename to startup_scripts/040_custom_links.py diff --git a/startup_scripts/020_tags.py b/startup_scripts/050_tags.py similarity index 100% rename from startup_scripts/020_tags.py rename to startup_scripts/050_tags.py diff --git a/startup_scripts/290_webhooks.py b/startup_scripts/060_webhooks.py similarity index 100% rename from startup_scripts/290_webhooks.py rename to startup_scripts/060_webhooks.py diff --git a/startup_scripts/020_tenant_groups.py b/startup_scripts/070_tenant_groups.py similarity index 100% rename from startup_scripts/020_tenant_groups.py rename to startup_scripts/070_tenant_groups.py diff --git a/startup_scripts/030_tenants.py b/startup_scripts/080_tenants.py similarity index 100% rename from startup_scripts/030_tenants.py rename to startup_scripts/080_tenants.py diff --git a/startup_scripts/030_regions.py b/startup_scripts/090_regions.py similarity index 100% rename from startup_scripts/030_regions.py rename to startup_scripts/090_regions.py diff --git a/startup_scripts/040_sites.py b/startup_scripts/110_sites.py similarity index 100% rename from startup_scripts/040_sites.py rename to startup_scripts/110_sites.py diff --git a/startup_scripts/075_locations.py b/startup_scripts/120_locations.py similarity index 100% rename from startup_scripts/075_locations.py rename to startup_scripts/120_locations.py diff --git a/startup_scripts/070_rack_roles.py b/startup_scripts/130_rack_roles.py similarity index 100% rename from startup_scripts/070_rack_roles.py rename to startup_scripts/130_rack_roles.py diff --git a/startup_scripts/140_clusters.py b/startup_scripts/140_clusters.py deleted file mode 100644 index 2748f20..0000000 --- a/startup_scripts/140_clusters.py +++ /dev/null @@ -1,42 +0,0 @@ -import sys - -from dcim.models import 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, ClusterGroup, ClusterType - -clusters = load_yaml("/opt/netbox/initializers/clusters.yml") - -if clusters is None: - sys.exit() - -required_assocs = {"type": (ClusterType, "name")} - -optional_assocs = { - "site": (Site, "name"), - "group": (ClusterGroup, "name"), - "tenant": (Tenant, "name"), -} - -for params in clusters: - custom_field_data = pop_custom_fields(params) - - 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) - - cluster, created = Cluster.objects.get_or_create(**params) - - if created: - set_custom_fields_values(cluster, custom_field_data) - - print("🗄️ Created cluster", cluster.name) diff --git a/startup_scripts/080_racks.py b/startup_scripts/140_racks.py similarity index 100% rename from startup_scripts/080_racks.py rename to startup_scripts/140_racks.py diff --git a/startup_scripts/330_power_panels.py b/startup_scripts/150_power_panels.py similarity index 100% rename from startup_scripts/330_power_panels.py rename to startup_scripts/150_power_panels.py diff --git a/startup_scripts/340_power_feeds.py b/startup_scripts/160_power_feeds.py similarity index 100% rename from startup_scripts/340_power_feeds.py rename to startup_scripts/160_power_feeds.py diff --git a/startup_scripts/165_cluster_groups.py b/startup_scripts/165_cluster_groups.py deleted file mode 100644 index fedd292..0000000 --- a/startup_scripts/165_cluster_groups.py +++ /dev/null @@ -1,15 +0,0 @@ -import sys - -from startup_script_utils import load_yaml -from virtualization.models import ClusterGroup - -cluster_groups = load_yaml("/opt/netbox/initializers/cluster_groups.yml") - -if cluster_groups is None: - sys.exit() - -for params in cluster_groups: - cluster_group, created = ClusterGroup.objects.get_or_create(**params) - - if created: - print("🗄️ Created Cluster Group", cluster_group.name) diff --git a/startup_scripts/050_manufacturers.py b/startup_scripts/170_manufacturers.py similarity index 100% rename from startup_scripts/050_manufacturers.py rename to startup_scripts/170_manufacturers.py diff --git a/startup_scripts/090_device_roles.py b/startup_scripts/180_device_roles.py similarity index 100% rename from startup_scripts/090_device_roles.py rename to startup_scripts/180_device_roles.py diff --git a/startup_scripts/060_device_types.py b/startup_scripts/190_device_types.py similarity index 100% rename from startup_scripts/060_device_types.py rename to startup_scripts/190_device_types.py diff --git a/startup_scripts/140_devices.py b/startup_scripts/200_devices.py similarity index 100% rename from startup_scripts/140_devices.py rename to startup_scripts/200_devices.py diff --git a/startup_scripts/250_dcim_interfaces.py b/startup_scripts/210_dcim_interfaces.py similarity index 100% rename from startup_scripts/250_dcim_interfaces.py rename to startup_scripts/210_dcim_interfaces.py diff --git a/startup_scripts/100_platforms.py b/startup_scripts/220_platforms.py similarity index 100% rename from startup_scripts/100_platforms.py rename to startup_scripts/220_platforms.py diff --git a/startup_scripts/175_route_targets.py b/startup_scripts/230_route_targets.py similarity index 100% rename from startup_scripts/175_route_targets.py rename to startup_scripts/230_route_targets.py diff --git a/startup_scripts/180_vrfs.py b/startup_scripts/240_vrfs.py similarity index 100% rename from startup_scripts/180_vrfs.py rename to startup_scripts/240_vrfs.py diff --git a/startup_scripts/150_rirs.py b/startup_scripts/250_rirs.py similarity index 100% rename from startup_scripts/150_rirs.py rename to startup_scripts/250_rirs.py diff --git a/startup_scripts/260_asns.py b/startup_scripts/260_asns.py new file mode 100644 index 0000000..893f3ba --- /dev/null +++ b/startup_scripts/260_asns.py @@ -0,0 +1,33 @@ +import sys + +from ipam.models import ASN, RIR +from startup_script_utils import load_yaml +from tenancy.models import Tenant + +asns = load_yaml("/opt/netbox/initializers/asns.yml") + +if asns is None: + sys.exit() + +required_assocs = {"rir": (RIR, "name")} + +optional_assocs = {"tenant": (Tenant, "name")} + +for params in asns: + 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) + + asn, created = ASN.objects.get_or_create(**params) + + if created: + print(f"🔡 Created ASN {asn.asn}") diff --git a/startup_scripts/160_aggregates.py b/startup_scripts/270_aggregates.py similarity index 100% rename from startup_scripts/160_aggregates.py rename to startup_scripts/270_aggregates.py diff --git a/startup_scripts/190_prefix_vlan_roles.py b/startup_scripts/280_prefix_vlan_roles.py similarity index 100% rename from startup_scripts/190_prefix_vlan_roles.py rename to startup_scripts/280_prefix_vlan_roles.py diff --git a/startup_scripts/130_cluster_types.py b/startup_scripts/290_cluster_types.py similarity index 100% rename from startup_scripts/130_cluster_types.py rename to startup_scripts/290_cluster_types.py diff --git a/startup_scripts/135_cluster_groups.py b/startup_scripts/300_cluster_groups.py similarity index 100% rename from startup_scripts/135_cluster_groups.py rename to startup_scripts/300_cluster_groups.py diff --git a/startup_scripts/135_clusters.py b/startup_scripts/310_clusters.py similarity index 100% rename from startup_scripts/135_clusters.py rename to startup_scripts/310_clusters.py diff --git a/startup_scripts/200_vlan_groups.py b/startup_scripts/320_vlan_groups.py similarity index 100% rename from startup_scripts/200_vlan_groups.py rename to startup_scripts/320_vlan_groups.py diff --git a/startup_scripts/210_vlans.py b/startup_scripts/330_vlans.py similarity index 100% rename from startup_scripts/210_vlans.py rename to startup_scripts/330_vlans.py diff --git a/startup_scripts/230_virtual_machines.py b/startup_scripts/340_virtual_machines.py similarity index 100% rename from startup_scripts/230_virtual_machines.py rename to startup_scripts/340_virtual_machines.py diff --git a/startup_scripts/240_virtualization_interfaces.py b/startup_scripts/350_virtualization_interfaces.py similarity index 100% rename from startup_scripts/240_virtualization_interfaces.py rename to startup_scripts/350_virtualization_interfaces.py diff --git a/startup_scripts/220_prefixes.py b/startup_scripts/360_prefixes.py similarity index 100% rename from startup_scripts/220_prefixes.py rename to startup_scripts/360_prefixes.py diff --git a/startup_scripts/260_ip_addresses.py b/startup_scripts/370_ip_addresses.py similarity index 99% rename from startup_scripts/260_ip_addresses.py rename to startup_scripts/370_ip_addresses.py index 3f0aed0..7f166f0 100644 --- a/startup_scripts/260_ip_addresses.py +++ b/startup_scripts/370_ip_addresses.py @@ -52,6 +52,7 @@ for params in ip_addresses: params["assigned_object_id"] = Interface.objects.get(**query).id else: query = {field: params.pop(assoc)} + params[assoc] = model.objects.get(**query) ip_address, created = IPAddress.objects.get_or_create(**params) diff --git a/startup_scripts/270_primary_ips.py b/startup_scripts/380_primary_ips.py similarity index 100% rename from startup_scripts/270_primary_ips.py rename to startup_scripts/380_primary_ips.py diff --git a/startup_scripts/320_services.py b/startup_scripts/400_services.py similarity index 100% rename from startup_scripts/320_services.py rename to startup_scripts/400_services.py diff --git a/startup_scripts/280_providers.py b/startup_scripts/420_providers.py similarity index 100% rename from startup_scripts/280_providers.py rename to startup_scripts/420_providers.py diff --git a/startup_scripts/290_circuit_types.py b/startup_scripts/440_circuit_types.py similarity index 100% rename from startup_scripts/290_circuit_types.py rename to startup_scripts/440_circuit_types.py diff --git a/startup_scripts/300_circuits.py b/startup_scripts/450_circuits.py similarity index 100% rename from startup_scripts/300_circuits.py rename to startup_scripts/450_circuits.py