Compare commits

...

436 Commits

Author SHA1 Message Date
a51ad36801 Merge pull request #355 from netbox-community/develop
Version 0.26.2
2020-10-27 16:41:48 +01:00
953ee09b0c Preparation for 0.26.2 2020-10-27 16:24:10 +01:00
94047d60ed Merge branch 'release' into develop 2020-10-27 16:22:59 +01:00
80bfd98000 Merge pull request #354 from comphilip/release
Fix ldap configuration in /etc/netbox/config/ldap/*.py not loaded
2020-10-27 16:11:55 +01:00
7694fd320a use extend method for simplification.
Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com>
2020-10-27 21:12:26 +08:00
097bea8702 Merge pull request #353 from netbox-community/develop
Version 0.26.1
2020-10-27 12:32:43 +01:00
a3c21ae0ac Fix ldap configuration in /etc/netbox/config/ldap/*.py not loaded 2020-10-27 19:27:51 +08:00
074960327b Preparation for 0.26.1 2020-10-27 10:30:55 +01:00
e1462d9ca4 Merge pull request #351 from netbox-community/RevertPrometheusPreps
Revert changes to 'gunicorn_config.py'
2020-10-27 10:29:07 +01:00
a5aa1bfd3b Revert changes to 'gunicorn_config.py' 2020-10-27 09:31:47 +01:00
cb02450783 Merge pull request #350 from comphilip/release
Fix "'NoneType' object has no attribute 'lower'" when no AUTH_LDAP_MI…
2020-10-27 09:29:34 +01:00
8307560c88 Fix "'NoneType' object has no attribute 'lower'" when no AUTH_LDAP_MIRROR_GROUPS defined 2020-10-27 15:51:12 +08:00
43aea3a1dd Merge pull request #349 from netbox-community/develop
Version 0.26.0
2020-10-26 16:55:21 +01:00
a52a5547be Preparation for 0.26.0 2020-10-26 16:21:47 +01:00
120a605d35 Merge pull request #347 from tobiasge/python-final
Use release version of Python 3.9 in tests
2020-10-26 16:06:12 +01:00
e51f9cbc18 Merge pull request #344 from netbox-community/Prometheus
Prepare for Monitoring with Prometheus
2020-10-26 15:58:52 +01:00
071401b771 Merge pull request #346 from tobiasge/fix-action-warning
Fix warning in Github Actions
2020-10-26 15:48:50 +01:00
911488242f Use release version of Python 3.9 in tests 2020-10-26 15:42:31 +01:00
5512ea68b3 Ignore prometheus.yml 2020-10-26 15:40:22 +01:00
7d055fbcaf Mention monitoring in README 2020-10-26 15:29:41 +01:00
3d244a1946 Fix warning in Github Actions
Our build script is using "set-env" which has been deprecated by Github.
See this bolg entry:
https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
2020-10-26 15:23:17 +01:00
e18d6c53b3 Revert most changes 2020-10-26 15:22:56 +01:00
48decdeb0e Monitoring parts to docker-compose.monitorin.yml 2020-10-26 15:22:56 +01:00
6ac65a64c9 Fix test 2020-10-26 15:22:56 +01:00
f46d8a7782 Adds Prometheus/Grafana monitoring infrastructure 2020-10-26 15:22:52 +01:00
64d82b5e42 Merge pull request #343 from netbox-community/DynamicVariables
Dynamic Configuration
2020-10-26 15:21:42 +01:00
58050e5287 Merge core functionality into configuration.py
Which is the file `docker/configuration.docker.py` in our repo.
The common code is then imported by `docker/ldap_config.docker.py`.
2020-10-26 14:43:11 +01:00
2dba2b8811 Fix default for secret_key in configuration.py 2020-10-20 21:45:37 +02:00
d0c7b87925 Improve order in configuration.py 2020-10-20 21:40:14 +02:00
ec3fd8a790 Revert accidential change to _read_secret order 2020-10-20 21:36:40 +02:00
75554ef5b4 Consistency in namespace name 2020-10-20 21:29:08 +02:00
dad0608834 Rename example.py to extra.py
And add some comments to the the file that hopefully guide the user.
2020-10-20 20:51:43 +02:00
dc77f1a0b1 Ignore non-default configuration files 2020-10-20 20:51:43 +02:00
16b567939c Dot character has special meaning in module names
Therefore we esacpe it using the underscore character.
2020-10-20 20:51:43 +02:00
20820e10c2 Optimize Imports in ldap_config.py 2020-10-20 20:51:35 +02:00
553c8ea470 Update configuration.py 2020-10-20 20:49:59 +02:00
811618b359 Lower gunicorn default loglevel 2020-10-20 20:46:43 +02:00
7429835970 Sample dynamic configuration file 2020-10-20 20:46:43 +02:00
43c05d816d Dynamically load configuration files 2020-10-20 20:46:43 +02:00
fd3d3d11d1 Tiny refactoring 2020-10-20 20:46:43 +02:00
121c3f800d Merge branch 'eemil-develop' into develop 2020-10-20 19:23:11 +02:00
9287995df4 Update to latest configuration 2020-10-20 19:22:52 +02:00
85fbb0af70 fix typo
Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com>
2020-10-20 19:20:29 +02:00
6bada6660a Prefer secret to env variable if both are configured 2020-10-20 19:20:29 +02:00
df3ab69c0f Merge pull request #310 from shuichiro-makigaki/add-remote-auth
Add REMOTE_AUTH_* configs
2020-10-20 09:02:27 +02:00
38f4474b14 Add REMOTE_AUTH_* support 2020-10-20 11:11:32 +09:00
51331621ab Merge pull request #345 from netbox-community/enable_sponsoring
Enable Sponsoring Button
2020-10-19 17:13:34 +02:00
156681f68d Merge pull request #327 from madnutter56/mirror_ldap_groups
add option to mirror ldap groups into netbox
2020-10-19 17:06:51 +02:00
9f4a9f528c add option to mirror ldap groups into netbox
this commit allows ldap assigned groups to be mirrored into
netbox users.

The default is None as this is not the primary way to do this
change.
2020-10-19 07:50:33 -07:00
cad803ed31 Create FUNDING.yml to enable sponsoring 2020-10-19 16:50:04 +02:00
9efaccadf7 Merge branch 'Tassatux-develop' into develop 2020-10-18 11:41:03 +02:00
f553d17655 Change log message 2020-10-18 11:31:48 +02:00
2b361c4541 Merge branch 'develop' of https://github.com/Tassatux/netbox-docker into Tassatux-develop 2020-10-18 11:24:51 +02:00
c744603a85 Merge pull request #336 from ericgeldmacher/develop
Fix sites.yml initializer
2020-09-21 21:04:39 +02:00
1133ef50de Fix sites.yml initializer 2020-09-15 15:38:24 -05:00
b33a509e25 Merge pull request #333 from tobiasge/python-3.8
Move default source image to Python 3.8
2020-09-01 15:35:17 +02:00
79f0b997f3 Merge pull request #332 from tobiasge/image-deps
Update images in docker-compose
2020-09-01 14:04:21 +02:00
32cef1dcf8 Enable test on Python 3.9 2020-09-01 13:52:01 +02:00
74833a9b21 Update images in docker-compose 2020-09-01 13:34:42 +02:00
a68f315acb Move default source image to Python 3.8 2020-09-01 12:27:39 +02:00
00022e7d79 Merge pull request #331 from netbox-community/develop
Develop
2020-09-01 11:05:25 +02:00
dd490605ca Preparation for 0.25.0 2020-09-01 10:40:16 +02:00
e2711ca205 Merge pull request #326 from tobiasge/fix-startup-2.9
Fixes for Netbox 2.9
2020-09-01 10:37:37 +02:00
a87f2b3331 Merge pull request #329 from tdorsey/patch-1
Fix typo in Readme
2020-08-31 08:03:33 +02:00
f174749f98 chore: fix typo 2020-08-30 22:06:20 -04:00
b02a93904e Fixed IP address creation for Netbox 2.9 2020-08-24 14:20:35 +02:00
3ace32dfc2 Fixed creation of passwords for Netbox 2.9 2020-08-24 11:08:28 +02:00
9fae2b0f74 Fixed VM interface creation for Netbox 2.9 2020-08-24 11:08:23 +02:00
23c3240863 Merge pull request #319 from jamiereid/release
Update README.md
2020-07-14 09:09:20 +02:00
3f9e874d77 Update README.md
fix spelling mistake
2020-07-14 11:19:49 +10:00
4b0f158852 Merge pull request #313 from jgcasd/jgcasd-patch-1
Add optional LOGIN_TIMEOUT to configuration.py
2020-06-17 15:26:16 +02:00
51490d0039 Added LOGIN_TIMEOUT option to configuration.py
Added LOGIN_TIMEOUT option to configuration.py. The option is already available in standard Netbox configuration.
2020-06-16 11:27:59 -07:00
df72d6bbb5 Handle primary IPs on devices and VMs 2020-06-05 13:12:27 +02:00
688672de26 Merge pull request #308 from netbox-community/XForwardedProto
Remove the 'X-Forwarded-Proto' line from the nginx config
2020-06-05 11:57:23 +02:00
5624ecc65e Remove the 'X-Forwarded-Proto' line from the nginx config
The reason is that in the default configuration nginx is only serving 'http' traffic.
So if an upstream proxy sets the 'X-Forwarded-Proto' header, because it is terminating
TLS, then nginx will overwrite it to 'http'. This will cause django to think the page
is served via 'http' and it will not create 'https://...' URLs.

Related to #292
2020-06-02 16:06:52 +02:00
7f93b328af Merge pull request #307 from netbox-community/FixFileMatching
Don't try to run non-python files
2020-06-02 14:42:58 +02:00
ccad15ecf7 Don't try to run non-python files 2020-06-02 13:37:57 +02:00
e9a9d9b70b Merge pull request #305 from netbox-community/develop
Preparation for 0.24.1
2020-05-29 14:41:15 +02:00
03b36058cd Preparation for 0.24.1 2020-05-29 10:09:08 +02:00
9e06a38d41 Merge pull request #304 from tobiasge/fix-303
Fix #303 for Netbox v2.8.5
2020-05-29 10:03:22 +02:00
b7ad18afb0 Fix #303 for Netbox v2.8.5
In this Netbox version the ColorChoices where moved to utilities.choiceFix #303 for Netbox v2.8.5

In this Netbox version the ColorChoices where moved to utilities.choicess
2020-05-27 09:10:24 +02:00
a9232e4f30 Add optional primary_ip on virtual machines initializer 2020-05-22 17:40:11 +02:00
93a3784295 Merge pull request #296 from netbox-community/develop
Release 0.24.0
2020-05-16 18:56:06 +02:00
45f7823a17 Preparation for 0.24.0 2020-05-15 13:59:45 +02:00
a6584d2874 Merge pull request #274 from tobiasge/optimise-builds
Optimise builds
2020-05-15 13:57:43 +02:00
fd87c7cb98 Merge pull request #294 from netbox-community/Fix284
Fix #284: Fixes the bug that initializers with no data stopped the execution of the later initializers
2020-05-15 13:57:23 +02:00
1f38ca0a86 Merge pull request #295 from minitriga/#293_ssl_tls_env
Implement SSL and TLS Config
2020-05-15 09:29:02 +02:00
efec435ba0 fix some issues 2020-05-14 15:37:47 +00:00
ab8ff04852 #293 2020-05-14 15:09:25 +00:00
77feec30a0 Don't stop when startup_scripts quit
Fixes #284
2020-05-14 16:59:30 +02:00
bed40b0d05 Add STARTTLS option. (#277)
* Add STARTTLS option.
2020-05-14 16:41:42 +02:00
24f0545bc6 Merge branch 'ryanmerolle-develop' into develop 2020-05-14 16:20:07 +02:00
1bc1ab2a0a Preserve compatibility 2020-05-14 16:19:38 +02:00
bfa69dc0e9 Merge branch 'develop' of https://github.com/ryanmerolle/netbox-docker into ryanmerolle-develop 2020-05-14 16:17:59 +02:00
6c8042b63d Merge pull request #289 from weisdd/bugfix/devices.py.example
Fixes #246: Non-working devices.py.example
2020-05-14 15:35:34 +02:00
795e82be46 Fix shellcheck error 2020-05-14 13:54:40 +02:00
d8a6c321a1 Update build.sh
Include suggestion from cimnine

Co-authored-by: Christian Mäder <cimnine@users.noreply.github.com>
2020-05-14 13:49:19 +02:00
1ecf4853b8 Fixed devices.py.example report 2020-05-11 16:46:10 +03:00
5cb8e97e65 Merge pull request #276 from weisdd/bugfix/dockerfile-media-permissions
Dockerfile: Fixed file permissions for media
2020-05-06 18:40:00 +02:00
98e131fa30 Merge pull request #279 from hoanhan101/release
Fix typo in overriding docker-compose config
2020-04-22 22:51:44 +02:00
d6323ce40f Fix typo in overriding docker-compose config 2020-04-22 16:24:34 -04:00
1c65f7af10 Dockerfile: Fixed file permissions for media 2020-04-18 17:08:42 +03:00
7fb78b3fd2 Fixed script in case no branch for next exists
Build now prints a message when no devlop-* branch is found instead of crashing
2020-04-13 21:44:18 +02:00
aa9f01a778 Merge pull request #273 from cimnine/NoResponse
No response
2020-04-09 21:17:42 +02:00
786f9b50d2 Fixes build when DOCKER_FROM is set but empty
The DOCKER_FROM is set to an empty value in the push tests.
This expands the check to catch this test case
2020-04-09 10:26:21 +02:00
5909670690 Fixed "latest" tag
The variable for the latest tag didn't contain all the needed values.
2020-04-09 09:04:20 +02:00
231de236e0 Removed Travis CI configuration and script
We are no longer building the images with Travis CI.
2020-04-09 08:47:07 +02:00
9ea95950b9 probot/no-response configuration 2020-04-09 08:30:30 +02:00
d84c399c00 Let "latest" tag follow the highest version
Latest tag is now added to the new version when it is release by Netbox.
2020-04-09 08:17:05 +02:00
a217ce8ffd Changed "build-branches.sh" to "build-next.sh"
The old version of "build-branches.sh" skipped the pushing of images when one of
them didn't change its sources. When looking at the Netbox branches I noticed
that the "master" branch only changes when there is a new release. Because we
build the new releases anyway in "build-latest.sh" that leaves "develop" and
"develop-*" which change regularly. The new script "build-next.sh" is responsible
for building "develop-*" as the next major release of Netbox. The build of
"develop" is moved to the Github Action build matrix. This has the additional
advantage of being faster because more builds are done in parallel.
2020-04-08 22:11:37 +02:00
794fb45e0e Fix shellcheck items found by shellcheck 0.7.1 2020-04-08 16:06:55 +02:00
8e34f46bad Add checks to verifiy if a new build is needed
This checks if the source materials (python image, Netbox commit,
netbox-docker commit) have changed since the last build. This check is done
by comparing the digest and commit ids from the previous image with the
given tag to the current values taken from the Git and Docker repositories.

The checks are only performed for builds by the automated builds on Github.
2020-04-08 15:50:06 +02:00
ed0d099df7 Merge pull request #271 from tobiasge/labels-in-build
Add labels for all variants
2020-04-05 13:14:48 +02:00
26d08302e3 Add labels for all variants
When we don't set the --label argument on the commandline for all
build variants we lose them in the image.
This also prints out the labes on image push.
2020-04-05 09:29:31 +02:00
64b763429f update configuration.py for netbox 2.7.11 REDIS config
update configuration.py to use REDIS config referencing `tasks` in place of `webhooks`
2020-04-01 23:41:35 -04:00
5769684c98 Merge pull request #265 from netbox-community/develop
Release 0.23.0
2020-03-30 20:51:22 +02:00
23e2da52f8 Preparation for 0.23.0 2020-03-30 15:15:30 +02:00
edba1a22fc Merge pull request #263 from general-programming/RELEASE_CHECK_URL
Add RELEASE_CHECK_URL to configuration and default env.
2020-03-30 15:13:59 +02:00
f87ffe7c33 Update configuration/configuration.py
Co-Authored-By: Christian Mäder <cimnine@users.noreply.github.com>
2020-03-29 01:40:08 -07:00
8bc77c1bc0 Add RELEASE_CHECK_URL to configuration and default env. 2020-03-27 21:34:51 -07:00
7662d81efe Merge pull request #258 from netbox-community/readme_improvements
Readme improvements
2020-03-17 16:39:43 +01:00
7f489aa11d Improved the README
- adjust the _Quick Start_ section to match the instructions in the _Getting Started_ guide on our wiki
- Adds a new _Getting Help_ section
- Improvements in explaining the tags of the published Docker image
2020-03-17 16:07:15 +01:00
5c3eff0823 Merge pull request #255 from minitriga/issue_253_docs_2
Fix embedded documents for Netbox version v2.7.10 and higher.
2020-03-11 12:16:48 +01:00
5f90ad8c56 inlude docs in container 2020-03-11 10:40:10 +00:00
5f1c241145 Merge pull request #245 from ScanPlusGmbH/fix-configuration-inconsistencies
Fix configuration inconsistencies
2020-03-11 09:53:21 +01:00
20c7461c7b Fixed test failures because of missing cache
When running tests with ´test.sh´ some errors where logged because now
redis-cache instance was running.
2020-02-14 12:38:05 +01:00
b9c44b85cc The Redis cache container was using the wrong env
Our docker-compose.yml pointed the env file for the Redis cache to the
wrong file. Now the Redis cache password between the netbox.env and
redis-cache.env match.
2020-02-14 12:38:05 +01:00
355ebadd10 Fixed configuration inconsistency for Redis cache
In the configuration.py we use database 1 as the default but in the .env
file we used 0. This sets both values to 1 as the default.
2020-02-14 12:38:05 +01:00
880628876f Merge pull request #244 from ScanPlusGmbH/init-perms-function
Permission handling in external function
2020-02-13 08:15:27 +01:00
8d3bd48c7a Permission handling in external function
This move the setting of user and group permissions in the startup
script to its own function.
2020-02-12 09:36:49 +01:00
882f7bcaf2 Merge pull request #238 from ScanPlusGmbH/remove-redundancy
Add function to load YAML files
2020-02-10 19:25:42 +01:00
50ade7bce1 Add function to load YAML files
This commit starts to remove some code redundancy from the startup
scripts for easier maintenance.
2020-02-10 07:47:17 +01:00
80f514fa90 Merge pull request #239 from netbox-community/develop
Release 0.22.0
2020-02-08 10:44:21 +01:00
c5822b9cec Merge pull request #235 from netbox-community/prepare-0.22.0
Prepare v0.22.0
2020-02-08 10:10:51 +01:00
e99a222a70 Prepare v0.22.0 2020-02-03 17:56:14 +01:00
3717b7469a Merge pull request #236 from netbox-community/LBegnaud-master
Permission Wildcards
2020-02-03 17:55:22 +01:00
3d80cc5a72 Tiny code refactoring 2020-02-02 09:48:02 +01:00
69ef7b7827 Removed the eval from the code
... and changed it to make it work with the latest Netbox version.
2020-01-31 11:39:05 +01:00
ba3176f140 Added missing keywords to the yaml
... and moved some documentatory comments to the beginning of the file.
2020-01-31 11:37:05 +01:00
a2c06026d5 Ajdust indents in __main__.py
... so that the match the style of the other python code in this project
2020-01-31 11:35:25 +01:00
f4e243d5ad update example to note yaml restriction 2020-01-31 09:27:34 +01:00
aa0d2a6e01 simplify yml definitions to use wildcard syntax 2020-01-31 09:27:34 +01:00
cce4370d41 add permission example 2020-01-31 09:27:34 +01:00
927a545f41 adjust groups and users startup scripts to allow custom codename filter 2020-01-31 09:27:34 +01:00
0574ffc571 Merge pull request #233 from newlandk/patch-1
update ldap caching configuration
2020-01-31 09:25:45 +01:00
ce74e94cbb Merge pull request #234 from netbox-community/test-pr
Enable push workflow for PRs
2020-01-31 09:18:31 +01:00
778f7546b8 Enable push workflow for PRs 2020-01-30 15:48:01 +01:00
74eaae6bc8 Update ldap_config.py 2020-01-28 17:43:35 -06:00
00986573d9 Update LDAP Caching Options
Update LDAP caching configuration to match changes made to django-auth-ldap in 1.6.0

Django social auth now uses different cache configuration options: https://github.com/django-auth-ldap/django-auth-ldap/blob/master/django_auth_ldap/backend.py#L1041-L1056

NetBox settings.py reference: https://github.com/netbox-community/netbox/blob/master/netbox/netbox/settings.py#L360
2020-01-28 17:36:45 -06:00
b0b20aa6ba Merge pull request #232 from netbox-community/develop
Release 0.21.1
2020-01-23 18:08:29 +01:00
f3a858811a Merge pull request #230 from netbox-community/prepare-0.21.1
Preparation for 0.21.1
2020-01-23 15:50:54 +01:00
1eb40d1774 Preparation for 0.21.1 2020-01-23 15:34:22 +01:00
1f25fba671 Merge pull request #229 from netbox-community/fix_shields
Readme Cleanup
2020-01-23 15:32:41 +01:00
f525351cfe Merge pull request #231 from netbox-community/green_tests
Disable python 3.9 tests once more
2020-01-23 15:31:46 +01:00
0e625a3b5c Disable python 3.9 tests once more 2020-01-23 10:44:02 +01:00
f0b00ee104 Update docker inspect command in bug_report template 2020-01-23 10:40:28 +01:00
1c8d695fc2 Remove references to the old build system 2020-01-23 10:36:13 +01:00
653321994a Fix link 2020-01-23 10:26:21 +01:00
132ab6fcca Fix typo in PR template 2020-01-23 10:09:56 +01:00
9229b45dc2 Fix build status badge 2020-01-23 09:35:30 +01:00
d058b7bc93 Merge pull request #226 from netbox-community/develop
Release 0.21.0
2020-01-23 08:59:05 +01:00
a0f5a11ff1 Merge branch 'release' into develop
This is to allow automatic merging on Github from develop->release
2020-01-20 11:32:56 +01:00
05b9431ecb Merge pull request #225 from netbox-community/prepare-0.21.0
Prepare 0.21.0
2020-01-20 11:28:13 +01:00
e179616db4 Preparation for 0.21.0 2020-01-20 10:36:15 +01:00
b92fbdc50d Update mentioned Netbox version to 2.7.1 2020-01-20 10:36:15 +01:00
f26df57bfd Merge pull request #218 from netbox-community/updated-pullrequest-template
Check that `develop` is the base branch in new PRs
2020-01-20 10:35:51 +01:00
8892ea9936 Ask for a release note entry 2020-01-20 10:28:08 +01:00
1bad9b4fa8 Fix typo in pull request template 2020-01-20 10:28:08 +01:00
2b21e14c2c Check that develop is target in PR
This is an update to the PR template.
It mostly adds text and some checks related to how good the template
is filled in and whether the `develop` branch was selected as base.
2020-01-20 10:28:08 +01:00
8caf755914 Merge pull request #209 from netbox-community/2.7-prep
Prepare for Netbox 2.7
2020-01-20 10:26:50 +01:00
27f671e41a Update IP Initializer for Netbox 2.7
The ip address database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your ip_addresses.yml
file as follows:

- Make sure the status is written in lower case.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
74a0e2cf6e Update Interfaces Initializer for Netbox 2.7
The interface database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your dcim_interfaces.yml
file as follows:

- Make sure the type is a value out of the possible choices.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
f3403cd0f5 Update VM Initializer for Netbox 2.7
The vm database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your virtual_machines.yml
file as follows:

- Make sure the status is spelled lowercase.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
8d8b9a157e Update VLAN Initializer for Netbox 2.7
The VLAN database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your vlans.yml file as follows:

- Make sure the status is spelled lowercase.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
4a58676647 Update Device Initializer for Netbox 2.7
The device database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your devices.yml file as
follows:

- Make sure the rack face is spelled lowercase.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
7b914d31d6 Update Rack Initializer for Netbox 2.7
The rack database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your racks.yml file as follows:

- Rack types must match one of the 5 rack types given, e.g.
  '4-post-cabinet'.
- Rack width must match one of the 2 rack widths given, i.e. '19' or
  '23'.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
c001626b85 Update Custom Fields Initializer for Netbox 2.7
The custom field database model has changed in Netbox 2.7.
Therefore the initializer code, that was used before, broke.
As a user, you will need to update your custom_fields.yml file as
follows:

- type must be lowercase
  - the `selection` type was changed to `select`
- the filter_logic must be lower case

This is to achieve compatibility with the naming schema that
Netbox uses internally. It allows us to become forward compatible
in case Netbox ever introduces a new type for custom fields.

See the diff of this commit for further information how this is meant.
2020-01-20 08:39:26 +01:00
355f9d4cf7 Prepare for Netbox 2.7 2020-01-20 08:39:26 +01:00
40ef427336 Merge pull request #222 from netbox-community/fix-github-action
Fix Github Action
2020-01-20 08:38:40 +01:00
e16b009a7f Merge pull request #221 from netbox-community/improve-test.sh
Improve test.sh
2020-01-20 08:37:48 +01:00
25671d42a5 Re-enable Netbox unit tests 2020-01-20 08:37:18 +01:00
dd0aee081a Fix failing GH Action 2020-01-17 18:46:30 +01:00
cfbd037f79 Enable tests with Python 3.9 2020-01-17 17:44:07 +01:00
3b56c827f9 Improve test.sh
Don't move the original initializers directory, but rather use the one
with the modified initializers in it.
2020-01-17 17:23:15 +01:00
870b44fdbc Merge pull request #214 from cimnine/github-action
Use Github Actions to build Netbox Docker
2020-01-17 14:26:40 +01:00
79a10dd445 Preparation for 0.20.0 2020-01-17 14:11:28 +01:00
57afeec94f Netbox is not yet compatible with Python 3.9 2019-12-29 22:09:32 +01:00
b118cd5812 Building the Docker image with Github Actions 2019-12-23 18:21:08 +01:00
7863e5902e Preparation for 0.20.0 2019-12-21 15:20:33 +01:00
0a9991de96 Merge pull request #186 from netbox-community/non-root
Non root
2019-12-20 14:21:34 +01:00
28c786c2a6 Merge pull request #195 from netbox-community/update-postgres
Update PostgreSQL to 11
2019-12-20 11:43:17 +01:00
1c899b55eb Merge pull request #201 from netbox-community/fix_docker_build
Fix variables for Dockerhub build
2019-12-20 11:42:59 +01:00
7af88388bb Merge pull request #202 from netbox-community/prepare_184
Prepares scripts and documentation for #184
2019-12-20 11:42:41 +01:00
51df2cbbaa Merge pull request #206 from netbox-community/test-initializers
Adds a test that validates the initializer yml files
2019-12-20 11:42:30 +01:00
b48de9f87e Merge pull request #207 from netbox-community/speedup_startup_scripts
Massive speedup in executing startup_scripts
2019-12-16 12:17:21 +01:00
85065005d4 Merge pull request #203 from netbox-community/pull-request-template
Pull Request Template Suggestion
2019-12-16 12:16:53 +01:00
0696ecb037 Merge pull request #204 from netbox-community/reduce_docker_context
Reduce the Docker Context
2019-12-16 12:16:37 +01:00
05d32ae705 Massive speedup in executing startup_scripts 2019-12-14 18:16:31 +01:00
fd955544af Merge pull request #196 from jsimonetti/rackgroup_initialiser
Add rack group initialiser
2019-12-14 17:31:38 +01:00
0a77c3d81e Merge pull request #198 from mattolenik/fix-197
Remove use of GNU date extensions when labeling images
2019-12-14 17:20:36 +01:00
66e90428b5 Remove use of GNU date extensions when labeling images
Fixes #197
2019-12-13 16:06:18 -08:00
310cda1f18 Reduce the Docker Context 2019-12-11 13:58:33 +01:00
daaf72962f Adds a test that validates the initializer yml files 2019-12-11 11:48:29 +01:00
93dee74459 Add rack group initialiser
Fixes #192

Signed-off-by: Jeroen Simonetti <jeroen@simonetti.nl>
2019-12-11 10:57:14 +01:00
1064696c96 N/A when there's no issue 2019-12-10 23:16:11 +01:00
7df5da38bf Pull request template suggestion 2019-12-10 23:09:43 +01:00
e4e0a63e17 Better safe than sorry, keep PostgreSQL at 11 for now. 2019-12-10 22:41:57 +01:00
bf2a21ddea Merge pull request #177 from sdktr/patch-2
Add SSLMODE to database connection settings
2019-12-10 22:39:53 +01:00
6a07527632 Merge pull request #194 from netbox-community/update-redis
Update Redis to Version 5
2019-12-10 22:35:55 +01:00
0f7675c792 Merge pull request #193 from netbox-community/revert-180
Revert "Fix #179 'libc not found'"
2019-12-10 22:35:39 +01:00
f3bbfdc34c Merge pull request #189 from netbox-community/GettingStarted
Adds a link to the Getting Started wiki section to the README
2019-12-10 22:35:17 +01:00
a4186c1031 Prepares scripts and documentation for #184 2019-12-10 21:44:11 +01:00
809570f4bc Fix variables for Dockerhub build 2019-12-10 21:25:36 +01:00
135199e597 Merge branch 'master' into patch-2 2019-12-09 22:54:30 +01:00
8a92640d10 Re-wording of dependencies check paragraph 2019-11-26 12:28:43 +01:00
788804627e Fix typo 2019-11-26 12:27:25 +01:00
150f35ea3b update postgres to 12 2019-11-26 12:23:16 +01:00
1ce99cf02f update redis 2019-11-26 12:14:51 +01:00
5e92352b0a set umask in entrypoint 2019-11-26 12:09:26 +01:00
8664e42233 Revert "Fix #179 'libc not found'"
This reverts commit feb810ab27.
2019-11-26 11:40:10 +01:00
7942e9edbe Remove the named user, change permissions to 'g+w' 2019-11-26 11:24:12 +01:00
01c4137dc9 Adds netbox user 2019-11-26 11:24:12 +01:00
c083baf640 Preparation for 0.19.4 2019-11-25 17:12:29 +01:00
d1d71e1256 Merge branch 'mattolenik-fix-skip-git' 2019-11-25 17:11:10 +01:00
6c762a7755 Merge branch 'fix-skip-git' of https://github.com/mattolenik/netbox-docker into mattolenik-fix-skip-git 2019-11-25 17:11:03 +01:00
946a503a25 Merge branch 'edenpark59-master' 2019-11-25 17:10:33 +01:00
6a8ffc1f02 Merge branch 'master' of https://github.com/edenpark59/netbox-docker into edenpark59-master 2019-11-25 17:10:22 +01:00
ca2b875ab9 Merge branch 'markhoney-patch-1' 2019-11-25 17:09:49 +01:00
29185fb9fd reorganized docker ignore file
.. and added some more files to it.
2019-11-25 17:09:37 +01:00
df7241ac5c Merge branch 'patch-1' of https://github.com/markhoney/netbox-docker into markhoney-patch-1 2019-11-25 17:07:12 +01:00
52d67f6b60 Merge branch 'labelling' 2019-11-25 17:06:43 +01:00
34ce5be006 Respect SKIP_GIT environment variable when building
Fixes issue #190
2019-11-21 08:09:01 -08:00
f2fd7dbbe7 Adds a link to the Getting Started wiki section to the README 2019-11-20 11:09:37 +01:00
08cda559a3 Update docker-compose.yml 2019-11-20 11:00:09 +01:00
02a5171e37 Update Nginx 1.17.6-alpine docker-compose.yml 2019-11-20 10:09:02 +01:00
552676cc9d Ignore local override file
Adding an ignore rule for docker-compose.override.yml should allow people to clone this repo and use an override file to match their environment, without that file causing issues every time they pull a new version of the repo.
2019-11-18 12:20:39 +13:00
caaa68234c Adds more labels to the Dockerfile
It also updates the README and the bug_report template to reflect
the changes. Additionally, in the README some relevant shields from
shields.io are added.

The labels follow [label-schema.org][lsorg] and the [OpenContainer
image spec, section annotations][ocis], specifications.

[lsorg]: http://label-schema.org/rc1/
[ocis]: https://github.com/opencontainers/image-spec/blob/master/annotations.md
2019-11-17 17:13:29 +01:00
eddc308055 Merge pull request #182 from netbox-community/feature-request-template
A new issue category for feature/change requests
2019-11-16 22:14:31 +01:00
0e2c50c374 A new issue category for feature/change requests 2019-11-12 11:56:22 +01:00
c790ce5953 Preparation for 0.19.3 2019-11-11 10:27:55 +01:00
cf7aef31e2 Merge pull request #180 from ScanPlusGmbH/fix-179
Fix #179 'libc not found'
2019-11-11 10:21:32 +01:00
feb810ab27 Fix #179 'libc not found'
Gunicorn version 20 crashes in this docker image. So for now use a
version <20.
2019-11-11 08:53:11 +01:00
3f2fe54bfd Merge pull request #176 from sdktr/patch-1
Add CONN_MAX_AGE to database connection settings
2019-11-11 08:29:47 +01:00
6568dff8e1 Add SSLMODE to database connection properties
Defaulting to SSLMODE=prefer, optional override using environment variable: DB_SSLMODE
2019-11-06 10:26:29 +01:00
773ec630b4 Add CONN_MAX_AGE to database connection settings
Defaulting to 300 seconds for the database connection to avoid new connection setup roundtrip on consecutive requests
2019-11-06 10:24:15 +01:00
8d71d2f973 Merge pull request #175 from ScanPlusGmbH/optimze-pip-install
Optimize pip install command
2019-11-01 14:20:20 +01:00
f9662a1e4b Optimize pip install command
As mentioned by @sdktr the "--install-option" is redundant. The added
"--no-warn-script-location" is used to silence warnings when installing
into a directory that is not on $PATH.
2019-10-31 10:11:33 +01:00
f7b526eacd Prepare Version 0.19.2 2019-10-24 17:03:14 +02:00
e32bb272b2 Merge branch 'ScanPlusGmbH-fix-170' 2019-10-24 17:02:47 +02:00
e3f632d77f Fixes #170 - "drf-yasg" installed into wrong dir
With the new multistage build the pip install command put some packages
in the wrong directory. This resuled in them not being copied into the
runtime images. This commit add the additional "--prefix" option to the
install command. After that all test run and we no longer get the error
"ModuleNotFoundError: No module named 'drf_yasg'".
2019-10-24 17:02:23 +02:00
63174f85ae Merge pull request #171 from tovin07/remove-trailing-space
Remove trailing space in Dockerfile
2019-10-24 16:47:50 +02:00
eb0f704ebe Remove trailing space in Dockerfile 2019-10-23 11:46:26 +07:00
b69a38015c Delete issue_template.md 2019-10-17 17:40:27 +02:00
41f6a80c91 Update issue templates 2019-10-17 17:40:01 +02:00
79f0670f7e Prepare Version 0.19.1 2019-10-15 12:29:35 +02:00
313d1a3aae Merge branch 'ScanPlusGmbH-custom-scripts' 2019-10-15 12:28:32 +02:00
8428b9cdbd Merge branch 'custom-scripts' of https://github.com/ScanPlusGmbH/netbox-docker into ScanPlusGmbH-custom-scripts 2019-10-15 12:28:22 +02:00
de1e3676eb Fix push 2019-10-15 12:28:04 +02:00
de1e5edd02 Prepare Version 0.19.0 2019-10-15 11:48:25 +02:00
ef989284c2 Merge pull request #159 from netbox-community/multistage-build
Refactor to multistage builds
2019-10-15 11:47:09 +02:00
e060f86b9a Corrections for shellcheck warnings 2019-10-15 10:03:39 +02:00
0a38220497 Update purpose text in build.sh 2019-10-15 01:00:21 +02:00
fb60841047 Only test 'latest' in PRs
Because it's the only tag being built
2019-10-15 00:56:37 +02:00
0f4a872082 More tests 2019-10-15 00:47:19 +02:00
26b1f59d66 Improve formating and fix typo 2019-10-15 00:40:48 +02:00
064908397e Improved Build Job descriptions 2019-10-15 00:34:15 +02:00
42642c94c3 Only push on 'main' branch 2019-10-15 00:34:15 +02:00
123fd981e9 Fix build
The Docker Hub build system runs on Ubuntu Xenial containers.
Xenial's git is 2.7.4, which does not know the `-P` flag yet.
2019-10-15 00:34:15 +02:00
20109c3392 Checkout the repository with git
This changes the build process even further. Instead
f using `wget` to fetch the current code, `git` is used.
This allows for faster switching between branches,
because only the differences between them have to be
fetched from the server.

But the main advantage is that the build cache can
finally be used as designed by Docker. Repetitive
builds are very fast now. This is also true between
branches and tags, as long as the `requirements.txt`
file doesn't change.
2019-10-15 00:34:15 +02:00
f3b9c34e3b externalize netbox download with wget 2019-10-15 00:34:15 +02:00
ab4b8720d1 Fix caching in build.sh 2019-10-15 00:34:15 +02:00
052b53aa5c Fix apt-get detection 2019-10-15 00:34:15 +02:00
fadac8c5c3 Only build the master branch to speed up the test 2019-10-15 00:34:15 +02:00
d0c9dfe2e5 Try to get PR builds working 2019-10-15 00:34:15 +02:00
d0ebb34432 Refactor to multistage builds
This commit introduces a huge change in the build process.

What changed:

- Dockerfile.ldap was integrated into Dockerfile as a seperate
  [build stage][multistage-build].
- All the build scripts were refactored according to this.
- The `docker-compose.yml` file was adjusted likewise.
- The main build script, `/build.sh`, now always builds all
  targets (formerly called variants).
- The minimal requirements for Docker and docker-compose
  have increased.
- The build on hub.docker.com must be adjusted.

This change should also fix #156 permanently.

[multistage-build]: https://docs.docker.com/develop/develop-images/multistage-build/
2019-10-15 00:34:15 +02:00
db04deca0d Add support for custom scripts
Custom scripts were added to Netbox in version 2.6.3. This adds a new
directory to the image where custom scripts can be placed.
2019-10-14 09:50:05 +02:00
c148d3ceb9 Prepare Version 0.18.2 2019-10-14 09:20:22 +02:00
42826ae133 Fix #165 2019-10-14 09:17:32 +02:00
19728fa3e6 prepare 0.18.1 2019-10-13 14:03:56 +02:00
e1f054b6b5 Merge branch 'fix-160' 2019-10-13 14:03:34 +02:00
79d349133e fix typo 2019-10-13 14:03:22 +02:00
cb8007e41d Adds a hyperlink for the #netbox-docker channel 2019-10-12 15:16:17 +02:00
b790796f9b Prepare Version 0.18.0 2019-10-12 14:56:03 +02:00
20c234a96e Introduce $SKIP_SUPERUSER
This adds a new variable to skip the creation of the superuser.
That is useful for LDAP and for production environments.

Fixes #160
2019-10-12 14:49:40 +02:00
5ae5977717 Merge branch 'axarriola-master' 2019-10-12 14:27:11 +02:00
e894cdaa06 Reformat initializers and add some IPv6 examples 2019-10-12 14:23:41 +02:00
5defc38294 Add missing break 2019-10-12 14:23:11 +02:00
61c0a9b519 Merge branch 'master' of https://github.com/axarriola/netbox-docker into axarriola-master 2019-10-12 14:02:35 +02:00
992a8f1d5f More typos. Tested all changes. 2019-10-11 18:08:22 +02:00
2d25907cba Fixing typos. 2019-10-11 17:30:38 +02:00
8a40c6e0a3 Merge branch 'master' of https://github.com/netbox-community/netbox-docker 2019-10-11 17:06:18 +02:00
ed8e339bfe Merge pull request #162 from netbox-community/cleanup
Remove debug statement
2019-10-11 16:32:07 +02:00
4b1514f8d3 Remove debug statement 2019-10-11 16:31:56 +02:00
2044f685cf Merge pull request #161 from netbox-community/fix-platform-initializer
Updating the initializer platform examples
2019-10-11 16:15:19 +02:00
86de0d850b Updating the initializer platform examples
rpc client was removed from netbox
2019-10-11 16:15:03 +02:00
4e1ac2392d Added newline and breaks. 2019-10-11 15:46:32 +02:00
723d4744a4 Merge branch 'master' of https://github.com/axarriola/netbox-docker into axarriola-master 2019-10-11 14:31:29 +02:00
821d6c8672 Fixed further requirements. 2019-10-10 17:35:06 +02:00
0b5214d247 Fixed aesthetics. 2019-10-10 16:52:29 +02:00
aca448d180 Merge branch 'bootc-helm-chart' 2019-10-09 12:42:01 +02:00
6051092a59 Move large parts of the documentation in the README to the wiki 2019-10-09 12:40:40 +02:00
03b52f9074 Merge branch 'helm-chart' of https://github.com/bootc/netbox-docker into bootc-helm-chart 2019-10-09 12:40:29 +02:00
ce9158eb07 Update README.md 2019-07-30 13:45:08 +02:00
74000645dc Make patch version 2019-07-30 13:36:22 +02:00
ef0755b9cf Merge pull request #149 from takumin/fix_attribute_error
fix AttributeError for ruamel.yaml
2019-07-30 13:34:48 +02:00
7f22d21d5d fix AttributeError for ruamel.yaml 2019-07-30 20:09:02 +09:00
e349c239fe Release 0.17.0 2019-07-30 10:47:56 +02:00
28ba0e56e7 Merge pull request #144 from ScanPlusGmbH/update-base-image
Update base image
2019-07-30 10:44:44 +02:00
b0287e344e Merge pull request #148 from LBegnaud/master
adjusts users and groups startup scripts to accomdate non-uniqueness
2019-07-30 10:44:03 +02:00
e6e7647f32 adjusts users and groups startup scripts to accomdate non-uniqueness 2019-07-26 14:13:15 -05:00
3e1f688f78 Add a link to my Helm chart
I've written and will continue to maintain a Helm chart to aid in
deploying NetBox on Kubernetes. This adds a link to the README file so
that people who may be interested in it can find it.
2019-07-20 16:51:51 -03:00
135d29e06f Update base image
This updates the base image to Alpine 3.10 with Python 3.7
2019-07-05 08:22:25 +02:00
4cb5b9f20d Added more startup_scripts and initializers examples. 2019-07-04 14:10:56 +02:00
5a4e9d7a14 Merge branch 'miso231-patch-1' 2019-07-02 21:33:54 +02:00
89b9c22252 Merge branch 'patch-1' of https://github.com/miso231/netbox-docker into miso231-patch-1 2019-07-02 21:33:36 +02:00
dc3db2d9fd %s/digitalocean/netbox-community/gi
Thank you Digitalocean for sponsoring Netbox!
And thank you for letting it grow up and move out ;)
2019-07-02 21:32:58 +02:00
0270fc2dca Retype REDIS_PORT to int 2019-07-01 17:29:58 +02:00
aed5126279 Provides necessary changes for v2.6 compatibility
Fixes #139
2019-06-21 22:48:23 +02:00
9c45e4d5e1 Prepare Version 0.14.0 2019-06-12 17:56:52 +02:00
dfd30f5eae Explain caching strategy in Dockerfile comments 2019-06-12 17:53:35 +02:00
a5537b18a4 Merge branch 'improved_build_speed' of https://github.com/rje6459/netbox-docker 2019-06-12 17:45:40 +02:00
9601cb1e54 Merge branch 'master' into improved_build_speed 2019-06-12 17:28:52 +02:00
54ac5dc2ab Merge branch 'mryauch-master' 2019-06-12 17:18:48 +02:00
a086c2fc22 Changing REF_URL to use HEAD/TAG agnostic API
Per [dicsuccion](https://github.com/netbox-community/netbox-docker/pull/137#issuecomment-495667921) with @cimnine, changing the API endpoint to one that retains functionality of previous URL while supporting both HEADS and TAGS
2019-05-28 10:45:10 -04:00
e33a2d2c0a Adding REF to GitHub repo HEAD for cache busting
After installing requirements, check if  HEAD has changed and bust cache for RUN instruction for wget  archive
2019-05-23 11:20:39 -04:00
821fb5f36e Caching of requirements.txt
After [a discussion][1] with rje6459 on the networktocode Slack
in the #netbox-docker channel we've come up with a small improvement
to those that regularly have to build netbox docker locally.

It fetches the "requirements.txt" from the desired branch before
downloading netbox itself.

[1]: https://networktocode.slack.com/archives/CD23LP8BC/p1558537080023200
2019-05-22 18:05:54 +02:00
7362e275b0 Add AUTH_LDAP_GROUP_TYPE env variable support
Dynamically imports the correct class/subclass from django_auth_ldap.config based on the AUTH_LDAP_GROUP_TYPE environment variable.
2019-05-09 07:47:28 -07:00
6c3db3deff Update django to 2.2 2019-05-09 09:57:01 +02:00
2f8ea89d54 Prepare Version 0.13.0 2019-05-08 12:00:57 +02:00
7008c03bcb Merge branch 'mryauch-mryauch-patch-1' 2019-05-08 11:57:50 +02:00
8f39034014 Merge branch 'mryauch-patch-1' of https://github.com/mryauch/netbox-docker into mryauch-mryauch-patch-1 2019-05-08 11:57:43 +02:00
98833e20c8 Prepare Version 0.12.0 2019-05-08 11:43:29 +02:00
a5e51dfb47 Merge branch 'ajknv-master' 2019-05-08 11:38:31 +02:00
936d868582 Merge branch 'master' of https://github.com/ajknv/netbox-docker into ajknv-master 2019-05-08 11:38:22 +02:00
96924736df Updated README.md to reflect AUTH_LDAP_BIND_PASSWORD secret support 2019-05-01 08:14:26 -07:00
5107fb7c6b AUTH_LDAP_BIND_PASSWORD secret file support 2019-04-30 14:24:22 -07:00
9eef398a9d prepare next version 2019-03-27 14:23:28 +01:00
e83db27b91 Merge pull request #131 from Bialogs/selinux
Add shared (z) container volume SELinux labels to the volumes created…
2019-03-27 14:19:18 +01:00
4419646732 Merge branch 'ScanPlusGmbH-short-tag' 2019-03-27 12:01:06 +01:00
286bfa0248 reorganized tagging 2019-03-27 12:00:32 +01:00
e768cb5b87 Merge branch 'short-tag' of https://github.com/ScanPlusGmbH/netbox-docker into ScanPlusGmbH-short-tag 2019-03-27 08:13:58 +01:00
e45773c29f Add shared (z) container volume SELinux labels to the volumes created by docker-compose. 2019-03-25 16:22:37 -04:00
220370ed76 Add short version tag
Adds a short version tag in the form of v$MAJOR.$MINOR. This tags
creates the possibillity to follow patch releases automatically with the
scheduled import option in Openshift and Kubernetes.
2019-03-22 08:28:41 +01:00
b49e6fac14 Update README.md
Fix the link to the configuration file, since it's core was "outsourced" some time ago.
2019-03-19 20:33:31 +01:00
5beb3093db Add support for using SSL connections to Redis. 2019-03-19 11:35:45 -05:00
df16a431ca Prepare Version 0.10.0
0.9.0 was already tagged without a version increment
2019-03-19 17:14:08 +01:00
585e411cde Prepare Version 0.9.0 2019-03-19 17:12:40 +01:00
e17baea76c Merge pull request #128 from ScanPlusGmbH/optimze-startup
Make startup scripts optional
2019-03-19 17:12:15 +01:00
8c95f32b0c Make startup scripts optional
To optimize the application boot time the startup scripts can now be
disabled by an ENV variable. The default when the variable is not set,
is to run the startup scripts. This means that the default behaviour is
not changed from earlier releases.
2019-03-11 12:31:41 +01:00
d4b394c999 Prepare 0.9.0 2019-02-22 14:03:42 +01:00
9c259adc88 Merge branch 'cimnine-update-django' 2019-02-22 13:53:49 +01:00
582064f4cd Loosen version pinning for Django
This change is in accordance with https://github.com/digitalocean/netbox/issues/2808
2019-02-22 13:52:37 +01:00
f8ea0f74ec Prepare 0.8.0 2019-02-22 13:49:48 +01:00
5cf9c3b4b1 Merge branch 'ScanPlusGmbH-master' 2019-02-22 13:46:28 +01:00
2450a70ca8 Update Alpine
This updates to the newest stable version (Alpine 3.9)
2019-02-21 15:30:40 +01:00
e9bea0a420 Update README.md 2019-02-07 09:49:11 +01:00
4895874845 Update README.md 2019-02-07 09:47:01 +01:00
7eca562252 Merge pull request #122 from cimnine/master
Fix DEBUG preventing build
2019-02-07 09:36:05 +01:00
fda1c272e9 fix DEBUG 2019-02-07 09:34:24 +01:00
609105e170 Merge pull request #121 from cimnine/master
Fix build target
2019-02-06 14:55:43 +01:00
740fa8128d Fix build target 2019-02-06 14:54:41 +01:00
9fdbd2f501 Merge pull request #120 from cimnine/master
Fix default in build.sh
2019-02-06 14:51:59 +01:00
c1946751ef Fix default in build.sh 2019-02-06 14:50:00 +01:00
a8b66fc082 Merge pull request #119 from cimnine/master
Remove deprecation warning for netboxcommunity images
2019-02-06 12:39:40 +01:00
ae9e945851 Remove deprecation warning for netboxcommunity images 2019-02-06 12:38:36 +01:00
fc1507a55d Merge pull request #118 from cimnine/consistent_variables
Consistent variable use in build scripts
2019-02-06 12:35:18 +01:00
c7ab15f914 Consistent variable use in build scripts 2019-02-06 12:30:08 +01:00
1c42f14bf0 Merge pull request #117 from cimnine/complete_migration
Update references to netboxcommunity
2019-02-06 11:47:44 +01:00
6182133c7a Update references to netboxcommunity 2019-02-06 11:46:20 +01:00
1e002846ef Merge pull request #116 from cimnine/docker-hub_build_system
Build system for hub.docker.com
2019-02-06 11:34:00 +01:00
09b4937b35 Update README 2019-02-06 11:24:01 +01:00
4ef420d443 Build system for hub.docker.com 2019-02-06 10:09:44 +01:00
5a09659278 Code style improvements 2019-01-30 13:58:23 +01:00
2f5d293fd6 ldap_config: resolve AUTH_LDAP_USER_SEARCH_ATTR and AUTH_LDAP_GROUP_SEARCH_CLASS from env 2019-01-19 05:12:36 -05:00
c9d9c7349e Remove duplicated entry in configuration.py 2019-01-09 09:03:24 +01:00
1fa07c6dc1 Bump VERSION file 2019-01-07 02:12:44 -08:00
c866bfff16 add note about breaking changes 2019-01-07 11:11:48 +01:00
44cdb73cc4 Merge pull request #109 from TakeMeNL/feature/105
#105 Change default api page size to 1000
2019-01-07 11:09:28 +01:00
20a86f0e98 Merge branch 'master' into feature/105 2019-01-07 10:47:15 +01:00
1f9ea8db53 Merge branch 'bdlamprecht-master' 2019-01-07 10:44:20 +01:00
db7daee86e formatted 2019-01-07 10:43:41 +01:00
0bae952410 Documenting reporting usage in README.md
Updated `README.md` on how to use the reporting feature of NetBox within this container.
2019-01-02 17:12:46 -07:00
34cd2cc577 Renamed devices.py to devices.py.example to set the example report to be disabled by default 2019-01-02 16:45:02 +00:00
e55580e3ae #105 Change default api page size to 1000 2018-12-27 22:12:17 +01:00
aab28d03ba Changing 'reports' from a volume to a mapped directory
This will allow eaiser interaction with the report functionality of the 'netbox' container.
2018-12-19 16:26:24 -07:00
eb09bf5364 Merge pull request #106 from ninech/ignore_missing_initializers
Ignore missing initializers
2018-12-19 17:03:56 +01:00
e46a7d2f7f Ignore missing initializers
Previously, the startup_scripts would fail if an initializer file was
not present. Now they just ignore missing files.
2018-12-19 14:25:58 +01:00
03eb153da4 Mention the #netbox-docker Slack channel 2018-11-12 21:54:14 +01:00
7675e8fc03 Update Breaking Changes list 2018-10-31 14:37:07 +01:00
d92f991cbe Bump VERSION file 2018-10-31 05:30:43 -07:00
c16f72a2ac Merge pull request #104 from ninech/add-more-seeds
Add seed/initialization scripts for additional resources
2018-10-31 13:27:54 +01:00
2fe139cb3c Reorder device types data 2018-10-31 10:58:42 +01:00
aa68548f41 Add Plaform seeds 2018-10-30 14:22:04 +01:00
a10cd805ae Prefix output messages with appropriate emoji 2018-10-30 10:51:43 +01:00
8b8620864c Replace trademarked names with generic ones 2018-10-30 10:11:05 +01:00
d145e9c719 Comply to README style 2018-10-30 10:07:33 +01:00
a120a95184 Fix initializers 2018-10-16 13:26:23 +02:00
97477556e0 Increase order prefix to 3 digits 2018-10-16 13:26:13 +02:00
7e6edd1bf5 Merge branch 'master' into add-more-seeds 2018-10-16 11:32:41 +02:00
b53e886f8f Handle all associations 2018-10-16 11:05:28 +02:00
63062a2634 Bump VERSION file 2018-10-16 00:38:22 -07:00
2b628b9826 Merge pull request #103 from ninech/permissions
Add permissions to user/group initializers
2018-10-16 09:37:41 +02:00
6cc4c67387 Remove default pop value 2018-10-16 09:12:43 +02:00
ab0ce20971 Update README 2018-10-15 15:15:56 +02:00
90ae5cf01d Add device seeds 2018-10-15 15:15:41 +02:00
ebb7779b5f Add device role seeds 2018-10-15 15:15:23 +02:00
60f7de1898 Add rack seeds 2018-10-15 15:15:09 +02:00
89fddbe0ab Add rack role seeds 2018-10-15 15:14:42 +02:00
a2b08a6ca5 Add device type seeds 2018-10-15 15:14:27 +02:00
86675278ab Add manufacturer seeds 2018-10-15 15:14:11 +02:00
791027f77b Add site seeds 2018-10-15 15:13:51 +02:00
819f325bd5 Add region seeds 2018-10-15 15:13:26 +02:00
4053a714f8 Add permissions to user/group initializers
Thank you @bdlamprecht for researching how to add permissions to
users and groups in #92.

Fixes #92
2018-10-13 17:44:01 +02:00
f1ebd4d246 Merge pull request #101 from ninech/cimnine-ntc-slack
Mention new Network-To-Code #netbox-docker Slack channel
2018-09-27 09:58:52 +02:00
68e6a62df1 Update README.md 2018-09-27 09:44:14 +02:00
81f8c7386d ✏️ Listed one more breaking change 2018-09-14 10:36:09 +02:00
ec1a253bde Bump VERSION file 2018-09-14 01:34:06 -07:00
bd1c58c91e ✏️ Mention update to Alpine 3.8 2018-09-14 10:21:26 +02:00
05070b3f9f Merge pull request #99 from ScanPlusGmbH/update-alpine
Update Alpine
2018-09-14 10:19:08 +02:00
ab72ba10c2 Update Alpine
This updates to the newest stable version (Alpine 3.8)
2018-09-14 09:43:09 +02:00
4c6ba58ef5 Merge pull request #98 from ninech/issues_96
🐞 REDIS_PORT should be int
2018-09-14 09:31:04 +02:00
6d74443f21 🐞 REDIS_PORT should be int
Closes #96
2018-09-14 08:50:13 +02:00
61414b7be7 Merge branch 'bdlamprecht-moving_env_files' 2018-09-14 08:49:27 +02:00
d8285b05f2 Moving env files into separate directory for better organization 2018-09-05 15:37:28 -06:00
968bb9f10f Prevent Github API Rate Limits
When building netbox-docker on Travis, it happened too often that the
build failed because of Github's API rate limits. These apply for all
requests, but if the request is unauthenticated they are applied by IP.

This is bad for netbox-docker, as we build on Travis where the build-
workers are shared with the rest of the world.

This commit adds the possibility to define OAuth credentials as
documented at [1]. Hopefully this leads to more reliable releases of
netbox-docker images.

[1] https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications
2018-08-28 09:21:08 -07:00
aafa6483dc fix wrong version increment 2018-08-16 08:19:49 -07:00
38ea286111 Bump VERSION file 2018-08-16 17:17:37 +02:00
be0ce47bc6 Merge pull request #91 from ninech/webhooks-backend
Webhooks Backend (based on #90)
2018-08-16 08:02:57 -07:00
2b3f831749 Don't lock Django to explicit version
... but rather use the same definition that is currently used in
Netbox's `requirements.txt`.
2018-08-14 10:08:34 -07:00
fb22a19893 ✏️ Added nginx troubleshooting section 2018-08-13 15:37:06 -07:00
fdefa3465d 🆙 Update nginx to the latest version 2018-08-13 15:30:43 -07:00
645ec1281c Use a default Redis password
Although it does not provide any additional security, it shows how to
configure Redis with a password and how to use Netbox using a password
protected redis server. Something that might be considered in a classic
production deployment. (But is mostly irrelevant in e.g. a Kubernetes /
OpenShift deployment as the isolation is usually on a network level.)
2018-08-13 15:19:29 -07:00
013f81b791 ♻️ Make netbox-worker it's own container
One container should ideally have one responsibility [1]. Therefore I
implemented the netbox-worker to start in it's own container. This is
possible, because netbox and the worker communicate via redis anyway.

They still use the same image underneath, just the "command" they
execute while starting different.

Or in other words: I see no reason to introduce supervisord, when we
already have docker-compose which can take care of running multiple
processes.

Also, here's another benefit: Now it's possible to view the logs of the
webhook worker independently of the other netbox logs (and vice-versa).

Other changes in this commit:
* I don't see a reason to put a password for Redis in the docker-compose
  setup, so I removed it.
* Slightly changed the nginx config, so that the nginx startup command
  becomes simpler and any error should be visible in the docker log.
* Some housekeeping in the `Dockerfile`.
* Added some troubleshooting advice regarding webhooks to the README.

I'd like to thank Brady (@bdlamprecht [2]) here who did the harder
work of figuring out what's even required to have webhooks working. [3]

[1] 
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#decouple-applications
[2] https://github.com/bdlamprecht
[3] https://github.com/ninech/netbox-docker/pull/90
2018-08-13 14:04:09 -07:00
b8885e4b79 Disable webhooks by default*
*but enable it by default for anyone who checks out the netbox-docker project
via the netbox.env file.
2018-08-13 13:17:41 -07:00
bf557877d1 Read redis password like any other secret 2018-08-13 13:16:10 -07:00
b88974ef9f Working implementation of webhooks using new 'redis' container 2018-08-10 17:55:09 -06:00
105 changed files with 3364 additions and 989 deletions

View File

@ -1,4 +1,10 @@
.git
.github
.travis.yml
*.md
env
build*
*.env
docker-compose.override.yml
.netbox/.git*
.netbox/.travis.yml
.netbox/scripts

14
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,14 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
- cimnine
- tobiasge
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

77
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,77 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
<!--
Before raising an issue here, answer the following questions for yourself, please:
* Did you read through the troubleshooting section? (https://github.com/netbox-community/netbox-docker/wiki/Troubleshooting)
* Have you had a look at the rest of the wiki? (https://github.com/netbox-community/netbox-docker/wiki)
* Have you updated to the latest version and tried again? (i.e. `git pull` and `docker-compose pull`)
* Have you reset the project and tried again? (i.e. `docker-compose down -v`)
* Are you confident that your problem is related to the Docker image or Docker Compose file this project provides?
(Otherwise ask on the Netbox mailing list, please: https://groups.google.com/d/forum/netbox-discuss)
* Have you looked through the issues already resolved?
Please try this means to get help before opening an issue here:
* On the networktocode Slack in the #netbox-docker channel: http://slack.networktocode.com/
* On the networktocode Slack in the #netbox channel: http://slack.networktocode.com/
* On the Netbox mailing list: https://groups.google.com/d/forum/netbox-discuss
Please don't open an issue when you have a PR ready. Just submit the PR, that's good enough.
-->
## Current Behavior
<!-- describe what you did and how it misbehaved -->
...
## Expected Behavior
<!-- describe what you expected instead -->
...
## Debug Information
<!-- please fill in the following information that might helps us debug your problem more quickly -->
The output of `docker-compose version`: `XXXXX`
The output of `docker version`: `XXXXX`
The output of `git rev-parse HEAD`: `XXXXX`
The command you used to start the project: `XXXXX`
<!-- adjust the `latest` tag to the version you're using -->
The output of `docker inspect netboxcommunity/netbox:latest --format "{{json .Config.Labels}}"`:
```json
{
"JSON JSON JSON":
"--> Please paste formatted json. (Use e.g. `jq` or https://jsonformatter.curiousconcept.com/)"
}
```
The output of `docker-compose logs netbox`:
<!--
If your log is very long, create a Gist instead (and post the link to it): https://gist.github.com
-->
```text
LOG LOG LOG
```
The output of `docker-compose logs nginx`:
<!--
Only if you have gotten a 5xx http error, else delete this section.
If your log is very long, create a Gist instead (and post the link to it): https://gist.github.com
-->
```text
LOG LOG LOG
```

View File

@ -0,0 +1,54 @@
---
name: Feature or Change Request
about: Request a new feature or a change of the current behavior
title: ''
labels: ''
assignees: ''
---
<!--
Before raising an issue here, answer the following questions for yourself, please:
* Did you read through the troubleshooting section? (https://github.com/netbox-community/netbox-docker/wiki/Troubleshooting)
* Have you had a look at the rest of the wiki? (https://github.com/netbox-community/netbox-docker/wiki)
* Have you read the release notes recently (https://github.com/netbox-community/netbox-docker/releases)
* Are you confident that your feature/change request is related to the Docker image or Docker Compose file this project provides?
(Otherwise ask on the Netbox mailing list, please: https://groups.google.com/d/forum/netbox-discuss)
* Have you looked through the issues already resolved?
Please try this means to get help before opening an issue here:
* On the networktocode Slack in the #netbox-docker channel: http://slack.networktocode.com/
* On the networktocode Slack in the #netbox channel: http://slack.networktocode.com/
* On the Netbox mailing list: https://groups.google.com/d/forum/netbox-discuss
Please don't open an issue when you have a PR ready. Just submit the PR, that's good enough.
-->
## Desired Behavior
<!-- please describe the behavior you desire -->
...
## Contrast to Current Behavior
<!-- please describe how the desired behavior is different from the current behavior -->
...
## Changes Required
<!-- if you can, please elaborate what changes would exactly be required -->
...
## Discussion: Benefits and Drawbacks
<!--
Please make your case here:
- Why do you think this project and the community will benefit from your suggestion?
- What are the drawbacks of this change? Is it backwards-compatible?
- Anything else that you think is relevant to the discussion of this feature/change request.
-->
...

View File

@ -1,47 +0,0 @@
<!--
Before raising an issue here, answer the following questions for yourself, please:
* Did you read through the troubleshooting section? (https://github.com/ninech/netbox-docker/#troubleshooting)
* Have you updated to the latest version and tried again? (i.e. `git pull` and `docker-compose pull`)
* Have you reset the project and tried again? (i.e. `docker-compose down -v`)
* Are you confident that your problem is related to the Docker or Docker Compose setup this project provides?
(Otherwise ask on the Netbox mailing list, please: https://groups.google.com/d/forum/netbox-discuss)
* Have you looked through the issues already resolved?
-->
## Current Behavior
<!-- describe what you did and how it misbehaved -->
...
## Expected Behavior
<!-- describe what you expected instead -->
...
## Debug Information
<!-- please fill in the following information that might helps us debug your problem more quickly -->
The output of `docker-compose version`: `XXXXX`
The output of `docker version`: `XXXXX`
The output of `git rev-parse HEAD`: `XXXXX`
The command you used to start the project: `XXXXX`
The output of `docker-compose logs netbox`:
<!-- if your log is very long, create a Gist instead: https://gist.github.com -->
```
LOG LOG LOG
```
<!--
If you have get any 5xx http error, else delete this section.
If your log is very long, create a Gist instead: https://gist.github.com
-->
The output of `docker-compose logs nginx`:
```
LOG LOG LOG
```

10
.github/no-response.yml vendored Normal file
View File

@ -0,0 +1,10 @@
# Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 30
# Label requiring a response
responseRequiredLabel: awaiting answer
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author.

85
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,85 @@
<!--
#########################################################################
Thank you for sharing your work and for opening a PR.
(!) IMPORTANT (!):
First make sure that you point your PR to the `develop` branch!
Now please read the comments carefully and try to provide information
on all relevant titles.
#########################################################################
-->
<!--
Please don't open an extra issue when submitting a PR.
But if there is already a related issue, please put it's number here.
E.g. #123 or N/A
-->
Related Issue:
## New Behavior
<!--
Please describe in a few words the intentions of your PR.
-->
...
## Contrast to Current Behavior
<!--
Please describe in a few words how the new behavior is different
from the current behavior.
-->
...
## Discussion: Benefits and Drawbacks
<!--
Please make your case here:
- Why do you think this project and the community will benefit from your
proposed change?
- What are the drawbacks of this change?
- Is it backwards-compatible?
- Anything else that you think is relevant to the discussion of this PR.
(No need to write a huge article here. Just a few sentences that give some
additional context about the motivations for the change.)
-->
...
## Changes to the Wiki
<!--
If the README.md must be updated, please include the changes in the PR.
If the Wiki must be updated, please make a suggestion below.
-->
...
## Proposed Release Note Entry
<!--
Please provide a short summary of your PR that we can copy & paste
into the release notes.
-->
...
## Double Check
<!--
Please put an x into the brackets (like `[x]`) if you've completed that task.
-->
* [ ] I have read the comments and followed the PR template.
* [ ] I have explained my PR according to the information in the comments.
* [ ] My PR targets the `develop` branch.

40
.github/workflows/push.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: push
on:
push:
branches-ignore:
- release
pull_request:
branches-ignore:
- release
jobs:
build:
strategy:
matrix:
build_cmd:
- ./build-latest.sh
- PRERELEASE=true ./build-latest.sh
- ./build-next.sh
- ./build.sh develop
docker_from:
- '' # use the default of the build script
- python:3.8-alpine
- python:3.9-alpine
fail-fast: false
runs-on: ubuntu-latest
name: Builds new Netbox Docker Images
steps:
- id: git-checkout
name: Checkout
uses: actions/checkout@v1
- id: docker-build
name: Build the image from '${{ matrix.docker_from }}' with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }}
env:
DOCKER_FROM: ${{ matrix.docker_from }}
GH_ACTION: enable
- id: docker-test
name: Test the image
run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh
if: steps.docker-build.outputs.skipped != 'true'

52
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: release
on:
push:
branches:
- release
schedule:
- cron: '45 5 * * *'
jobs:
build:
strategy:
matrix:
build_cmd:
- ./build-latest.sh
- PRERELEASE=true ./build-latest.sh
- ./build-next.sh
- ./build.sh develop
fail-fast: false
runs-on: ubuntu-latest
name: Builds new Netbox Docker Images
steps:
- id: git-checkout
name: Checkout
uses: actions/checkout@v2
- id: docker-build
name: Build the image with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }}
env:
GH_ACTION: enable
- id: docker-test
name: Test the image
run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh
if: steps.docker-build.outputs.skipped != 'true'
- id: registry-login
name: Login to the Docker Registry
run: |
echo "::add-mask::$DOCKERHUB_USERNAME"
echo "::add-mask::$DOCKERHUB_PASSWORD"
docker login -u "$DOCKERHUB_USERNAME" --password "${DOCKERHUB_PASSWORD}" "${DOCKER_REGISTRY}"
env:
DOCKERHUB_USERNAME: ${{ secrets.dockerhub_username }}
DOCKERHUB_PASSWORD: ${{ secrets.dockerhub_password }}
if: steps.docker-build.outputs.skipped != 'true'
- id: registry-push
name: Push the image
run: ${{ matrix.build_cmd }} --push-only
if: steps.docker-build.outputs.skipped != 'true'
- id: registry-logout
name: Logout of the Docker Registry
run: docker logout "${DOCKER_REGISTRY}"
if: steps.docker-build.outputs.skipped != 'true'

10
.gitignore vendored
View File

@ -1 +1,11 @@
*.sql.gz
.netbox
.initializers
docker-compose.override.yml
*.pem
configuration/*
!configuration/configuration.py
!configuration/extra.py
configuration/ldap/*
!configuration/ldap/ldap_config.py
prometheus.yml

View File

@ -1,32 +0,0 @@
sudo: required
language: python
env:
- BUILD=release
- BUILD=prerelease
- BUILD=branches
- BUILD=special
git:
depth: 5
services:
- docker
install:
- docker-compose pull --parallel
- docker-compose build
script:
- docker-compose run netbox ./manage.py test
after_script:
- docker-compose down
after_success:
- docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
- ./build-all.sh --push
notifications:
slack:
secure: F3VsWcvU/XYyjGjU8ZAVGpREe7F1NjKq6LuMRzhQORbXUvanxDQtLzEe0Y5zm/6+gHkx6t8cX/v2PiCI+v46pkapYMUimd+QEOL1WxbUdnw2kQxcgw/R3wX34l2FHXbG3/a+TmH3euqbSCTIrPy9ufju948i+Q0E0u0fyInmozl8qOT23C4joQOpVAq7y+wHxTxsEg46ZzL2Ties+dmqjMsvHocv7mPI2IWzAWA8SJZxS82Amoapww++QjgEmoY+tMimLkdeXCRgeoj41UGHDg54rbEXh/PTaWiuzyzTr1WLmsGRScC57fDRivp3mSM37/MlNxsRj1z+j4zrvWFQgNfJ2yMjBHroc1jOX/uCY4dwbpSPqUCpc4idMGCGZFItgzTQ3lAPYAsom0C6n8C08Xk8EsNKWwXrDSd4ZUhIwptkNPCFK+kXbLFsMzSApnaBYW0T+wba57nZdiWjOPYmvJr49MDm5NHv2KaRBX2gpw7t7ZLhTgwGEWcZvcDebiLneXcXY5hZ7v2NHJkx/2x1yNXo85xZDy0wK1FGoOOHwPhvqOB+pcQZ/pUOSPTKqGw5l/CexoRm1shFsK+19FnSgimqTHjcuCo4lFW3JlEvlFhtfFXIte2Wjp1ALZgTrSq8zSD5rRxYCUKmM7b3EJwdaIgbvKWPdS4sCXlXU1bHx0g=

View File

@ -1,4 +1,5 @@
FROM python:3.6-alpine3.7
ARG FROM
FROM ${FROM} as builder
RUN apk add --no-cache \
bash \
@ -6,50 +7,118 @@ RUN apk add --no-cache \
ca-certificates \
cyrus-sasl-dev \
graphviz \
ttf-ubuntu-font-family \
jpeg-dev \
libevent-dev \
libffi-dev \
libxml2-dev \
libxslt-dev \
openldap-dev \
postgresql-dev \
wget
postgresql-dev
RUN pip install \
WORKDIR /install
RUN pip install --prefix="/install" --no-warn-script-location \
# gunicorn is used for launching netbox
gunicorn \
greenlet \
eventlet \
# napalm is used for gathering information from network devices
napalm \
# ruamel is used in startup_scripts
ruamel.yaml
'ruamel.yaml>=0.15,<0.16' \
# django_auth_ldap is required for ldap
django_auth_ldap \
# django-storages was introduced in 2.7 and is optional
django-storages
ARG NETBOX_PATH
COPY ${NETBOX_PATH}/requirements.txt /
RUN pip install --prefix="/install" --no-warn-script-location -r /requirements.txt
###
# Main stage
###
ARG FROM
FROM ${FROM} as main
RUN apk add --no-cache \
bash \
ca-certificates \
graphviz \
libevent \
libffi \
libjpeg-turbo \
libressl \
libxslt \
postgresql-libs \
ttf-ubuntu-font-family
WORKDIR /opt
ARG BRANCH=master
ARG URL=https://github.com/digitalocean/netbox/archive/$BRANCH.tar.gz
RUN wget -q -O - "${URL}" | tar xz \
&& mv netbox* netbox
COPY --from=builder /install /usr/local
WORKDIR /opt/netbox
RUN pip install -r requirements.txt
ARG NETBOX_PATH
COPY ${NETBOX_PATH} /opt/netbox
COPY docker/configuration.docker.py /opt/netbox/netbox/netbox/configuration.py
COPY configuration/gunicorn_config.py /etc/netbox/config/
COPY docker/gunicorn_config.py /etc/netbox/
COPY docker/nginx.conf /etc/netbox-nginx/nginx.conf
COPY docker/docker-entrypoint.sh docker-entrypoint.sh
COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh
COPY startup_scripts/ /opt/netbox/startup_scripts/
COPY initializers/ /opt/netbox/initializers/
COPY configuration/configuration.py /etc/netbox/config/configuration.py
COPY configuration/ /etc/netbox/config/
WORKDIR /opt/netbox/netbox
# Must set permissions for '/opt/netbox/netbox/static' directory
# to g+w so that `./manage.py collectstatic` can be executed during
# container startup.
# Must set permissions for '/opt/netbox/netbox/media' directory
# to g+w so that pictures can be uploaded to netbox.
RUN mkdir static && chmod -R g+w static media
ENTRYPOINT [ "/opt/netbox/docker-entrypoint.sh" ]
VOLUME ["/etc/netbox-nginx/"]
CMD ["gunicorn", "-c /etc/netbox/gunicorn_config.py", "netbox.wsgi"]
CMD ["gunicorn", "-c /etc/netbox/config/gunicorn_config.py", "netbox.wsgi"]
LABEL ORIGINAL_TAG="" \
NETBOX_GIT_BRANCH="" \
NETBOX_GIT_REF="" \
NETBOX_GIT_URL="" \
# See http://label-schema.org/rc1/#build-time-labels
# Also https://microbadger.com/labels
org.label-schema.schema-version="1.0" \
org.label-schema.build-date="" \
org.label-schema.name="Netbox Docker" \
org.label-schema.description="A container based distribution of Netbox, the free and open IPAM and DCIM solution." \
org.label-schema.vendor="The netbox-docker contributors." \
org.label-schema.url="https://github.com/netbox-community/netbox-docker" \
org.label-schema.usage="https://github.com/netbox-community/netbox-docker/wiki" \
org.label-schema.vcs-url="https://github.com/netbox-community/netbox-docker.git" \
org.label-schema.vcs-ref="" \
org.label-schema.version="snapshot" \
# See https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys
org.opencontainers.image.created="" \
org.opencontainers.image.title="Netbox Docker" \
org.opencontainers.image.description="A container based distribution of Netbox, the free and open IPAM and DCIM solution." \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.authors="The netbox-docker contributors." \
org.opencontainers.image.vendor="The netbox-docker contributors." \
org.opencontainers.image.url="https://github.com/netbox-community/netbox-docker" \
org.opencontainers.image.documentation="https://github.com/netbox-community/netbox-docker/wiki" \
org.opencontainers.image.source="https://github.com/netbox-community/netbox-docker.git" \
org.opencontainers.image.revision="" \
org.opencontainers.image.version="snapshot"
LABEL SRC_URL="$URL"
#####
## LDAP specific configuration
#####
ARG NETBOX_DOCKER_PROJECT_VERSION=snapshot
LABEL NETBOX_DOCKER_PROJECT_VERSION="$NETBOX_DOCKER_PROJECT_VERSION"
FROM main as ldap
RUN apk add --no-cache \
libsasl \
libldap \
util-linux
COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py

View File

@ -1,9 +0,0 @@
ARG DOCKER_ORG=ninech
ARG DOCKER_REPO=netbox
ARG FROM_TAG=latest
FROM $DOCKER_ORG/$DOCKER_REPO:$FROM_TAG
RUN pip install django_auth_ldap
COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py
COPY configuration/ldap_config.py /etc/netbox/config/ldap_config.py

400
README.md
View File

@ -1,319 +1,161 @@
# netbox-docker
[![Build Status](https://travis-ci.org/ninech/netbox-docker.svg?branch=master)][travis]
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/netbox-community/netbox-docker)][github-release]
[![GitHub stars](https://img.shields.io/github/stars/netbox-community/netbox-docker)][github-stargazers]
![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed-raw/netbox-community/netbox-docker)
![Github release workflow](https://img.shields.io/github/workflow/status/netbox-community/netbox-docker/release)
![Docker Pulls](https://img.shields.io/docker/pulls/netboxcommunity/netbox)
[![MicroBadger Layers](https://img.shields.io/microbadger/layers/netboxcommunity/netbox)][netbox-docker-microbadger]
[![MicroBadger Size](https://img.shields.io/microbadger/image-size/netboxcommunity/netbox)][netbox-docker-microbadger]
[![GitHub license](https://img.shields.io/github/license/netbox-community/netbox-docker)][netbox-docker-license]
This repository houses the components needed to build NetBox as a Docker container.
Images built using this code are released to [Docker Hub][netbox-dockerhub] every night.
[The Github repository](netbox-docker-github) houses the components needed to build Netbox as a Docker container.
Images are built using this code and are released to [Docker Hub][netbox-dockerhub] once a day.
[travis]: https://travis-ci.org/ninech/netbox-docker
[netbox-dockerhub]: https://hub.docker.com/r/ninech/netbox/tags/
Do you have any questions?
Before opening an issue on Github, please join the [Network To Code][ntc-slack] Slack and ask for help in our [`#netbox-docker`][netbox-docker-slack] channel.
[github-stargazers]: https://github.com/netbox-community/netbox-docker/stargazers
[github-release]: https://github.com/netbox-community/netbox-docker/releases
[netbox-docker-microbadger]: https://microbadger.com/images/netboxcommunity/netbox
[netbox-dockerhub]: https://hub.docker.com/r/netboxcommunity/netbox/tags/
[netbox-docker-github]: https://github.com/netbox-community/netbox-docker/
[ntc-slack]: http://slack.networktocode.com/
[netbox-docker-slack]: https://slack.com/app_redirect?channel=netbox-docker&team=T09LQ7E9E
[netbox-docker-license]: https://github.com/netbox-community/netbox-docker/blob/release/LICENSE
## Docker Tags
* `vX.Y.Z`: These are release builds, automatically built from [the corresponding releases of Netbox][netbox-releases].
* `latest`: These are release builds, automatically built from [the `master` branch of Netbox][netbox-master].
* `snapshot`: These are pre-release builds, automatically built from the [`develop` branch of Netbox][netbox-develop].
* `develop-X.Y`: These are pre-release builds, automatically built from the corresponding [branch of Netbox][netbox-branches].
Then there is currently one extra tags for each of the above tags:
* `-ldap`: Contains additional dependencies and configurations for connecting Netbox to an LDAP directory.
[Learn more about that in our wiki][netbox-docker-ldap].
New images are built and published automatically every ~24h.
[netbox-releases]: https://github.com/netbox-community/netbox/releases
[netbox-master]: https://github.com/netbox-community/netbox/tree/master
[netbox-develop]: https://github.com/netbox-community/netbox/tree/develop
[netbox-branches]: https://github.com/netbox-community/netbox/branches
[netbox-docker-ldap]: https://github.com/netbox-community/netbox-docker/wiki/LDAP
## Quickstart
To get NetBox up and running:
To get Netbox Docker up and running run the following commands.
There is a more complete [_Getting Started_ guide on our wiki][wiki-getting-started] which explains every step.
```
$ git clone -b master https://github.com/ninech/netbox-docker.git
$ cd netbox-docker
$ docker-compose pull
$ docker-compose up -d
```bash
git clone -b release https://github.com/netbox-community/netbox-docker.git
cd netbox-docker
tee docker-compose.override.yml <<EOF
version: '3.4'
services:
nginx:
ports:
- 8000:8080
EOF
docker-compose pull
docker-compose up
```
The application will be available after a few minutes.
Use `docker-compose port nginx 8080` to find out where to connect to.
```
$ echo "http://$(docker-compose port nginx 8080)/"
http://0.0.0.0:32768/
# Open netbox in your default browser on macOS:
$ open "http://$(docker-compose port nginx 8080)/"
# Open netbox in your default browser on (most) linuxes:
$ xdg-open "http://$(docker-compose port nginx 8080)/" &>/dev/null &
```
Alternatively, use something like [Reception][docker-reception] to connect to _docker-compose_ projects.
Default credentials:
The whole application will be available after a few minutes.
Open the URL `http://0.0.0.0:8000/` in a web-browser.
You should see the Netbox homepage.
In the top-right corner you can login.
The default credentials are:
* Username: **admin**
* Password: **admin**
* API Token: **0123456789abcdef0123456789abcdef01234567**
[docker-reception]: https://github.com/ninech/reception
[wiki-getting-started]: https://github.com/netbox-community/netbox-docker/wiki/Getting-Started
[docker-reception]: https://github.com/nxt-engineering/reception
## Documentation
Please refer [to our wiki on Github][netbox-docker-wiki] for further information on how to use this Netbox Docker image properly.
It covers advanced topics such as using files for secrets, deployment to Kubernetes, monitoring and configuring NAPALM or LDAP.
[netbox-docker-wiki]: https://github.com/netbox-community/netbox-docker/wiki/
## Getting Help
Please join [our Slack channel `#netbox-docker`][netbox-docker-slack] on the [Network To Code Slack][ntc-slack].
It's free to use and there are almost always people online that can help.
If you need help with using Netbox or developing for it or against it's API you may find the `#netbox` channel on the same Slack instance very helpful.
## Dependencies
This project relies only on *Docker* and *docker-compose* meeting this requirements:
This project relies only on *Docker* and *docker-compose* meeting these requirements:
* The *Docker version* must be at least `1.13.0`.
* The *docker-compose version* must be at least `1.10.0`.
* The *Docker version* must be at least `17.05`.
* The *docker-compose version* must be at least `1.17.0`.
To ensure this, compare the output of `docker --version` and `docker-compose --version` with the requirements above.
To check the version installed on your system run `docker --version` and `docker-compose --version`.
## Configuration
## Use a Specific Netbox Version
You can configure the app using environment variables. These are defined in `netbox.env`.
Read [Environment Variables in Compose][compose-env] to understand about the various possibilities to overwrite these variables.
(The easiest solution being simply adjusting that file.)
To find all possible variables, have a look at the [configuration.docker.py][docker-config] and [docker-entrypoint.sh][entrypoint] files.
Generally, the environment variables are called the same as their respective NetBox configuration variables.
Variables which are arrays are usually composed by putting all the values into the same environment variables with the values separated by a whitespace ("` `").
For example defining `ALLOWED_HOSTS=localhost ::1 127.0.0.1` would allows access to NetBox through `http://localhost:8080`, `http://[::1]:8080` and `http://127.0.0.1:8080`.
[compose-env]: https://docs.docker.com/compose/environment-variables/
### Production
The default settings are optimized for (local) development environments.
You should therefore adjust the configuration for production setups, at least the following variables:
* `ALLOWED_HOSTS`: Add all URLs that lead to your NetBox instance.
* `DB_*`: Use a persistent database.
* `EMAIL_*`: Use your own mailserver.
* `MAX_PAGE_SIZE`: Use the recommended default of 1000.
* `SUPERUSER_*`: Only define those variables during the initial setup, and drop them once the DB is set up.
### Running on Docker Swarm / Kubernetes / OpenShift
You may run this image in a cluster such as Docker Swarm, Kubernetes or OpenShift, but this is advanced level.
In this case, we encourage you to statically configure NetBox by starting from [NetBox's example config file][default-config], and mounting it into your container in the directory `/etc/netbox/config/` using the mechanism provided by your container platform (i.e. [Docker Swarm configs][swarm-config], [Kubernetes ConfigMap][k8s-config], [OpenShift ConfigMaps][openshift-config]).
But if you rather continue to configure your application through environment variables, you may continue to use [the built-in configuration file][docker-config].
We discourage storing secrets in environment variables, as environment variable are passed on to all sub-processes and may leak easily into other systems, e.g. error collecting tools that often collect all environment variables whenever an error occurs.
Therefore we *strongly advise* to make use of the secrets mechanism provided by your container platform (i.e. [Docker Swarm secrets][swarm-secrets], [Kubernetes secrets][k8s-secrets], [OpenShift secrets][openshift-secrets]).
[The configuration file][docker-config] and [the entrypoint script][entrypoint] try to load the following secrets from the respective files.
If a secret is defined by an environment variable and in the respective file at the same time, then the value from the environment variable is used.
* `SUPERUSER_PASSWORD`: `/run/secrets/superuser_password`
* `SUPERUSER_API_TOKEN`: `/run/secrets/superuser_api_token`
* `DB_PASSWORD`: `/run/secrets/db_password`
* `SECRET_KEY`: `/run/secrets/secret_key`
* `EMAIL_PASSWORD`: `/run/secrets/email_password`
* `NAPALM_PASSWORD`: `/run/secrets/napalm_password`
Please also consider [the advice about running NetBox in production](#production) above!
[docker-config]: https://github.com/ninech/netbox-docker/blob/master/docker/configuration.docker.py
[default-config]: https://github.com/digitalocean/netbox/blob/develop/netbox/netbox/configuration.example.py
[entrypoint]: https://github.com/ninech/netbox-docker/blob/master/docker/docker-entrypoint.sh
[swarm-config]: https://docs.docker.com/engine/swarm/configs/
[swarm-secrets]: https://docs.docker.com/engine/swarm/secrets/
[openshift-config]: https://docs.openshift.org/latest/dev_guide/configmaps.html
[openshift-secrets]: https://docs.openshift.org/latest/dev_guide/secrets.html
[k8s-secrets]: https://kubernetes.io/docs/concepts/configuration/secret/
[k8s-config]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
### NAPALM Configuration
Since v2.1.0 NAPALM has been tightly integrated into NetBox.
NAPALM allows NetBox to fetch live data from devices and return it to a requester via its REST API.
To learn more about what NAPALM is and how it works, please see the documentation from the [libary itself][napalm-doc] or the documentation from [NetBox][netbox-napalm-doc] on how it is integrated.
To enable this functionality, simply complete the following lines in `netbox.env` (or appropriate secrets mechanism) :
* `NAPALM_USERNAME`: A common username that can be utilized for connecting to network devices in your environment.
* `NAPALM_PASSWORD`: The password to use in combintation with the username to connect to network devices.
* `NAPALM_TIMEOUT`: A value to use for when an attempt to connect to a device will timeout if no response has been recieved.
However, if you don't need this functionality, leave these blank.
[napalm-doc]: http://napalm.readthedocs.io/en/latest/index.html
[netbox-napalm-doc]: https://netbox.readthedocs.io/en/latest/configuration/optional-settings/#napalm_username
### Custom Initialization Code (e.g. Automatically Setting Up Custom Fields)
When using `docker-compose`, all the python scripts present in `/opt/netbox/startup_scripts` will automatically be executed after the application boots in the context of `./manage.py`.
That mechanism can be used for many things, e.g. to create NetBox custom fields:
```python
# docker/startup_scripts/load_custom_fields.py
from django.contrib.contenttypes.models import ContentType
from extras.models import CF_TYPE_TEXT, CustomField
from dcim.models import Device
from dcim.models import DeviceType
device = ContentType.objects.get_for_model(Device)
device_type = ContentType.objects.get_for_model(DeviceType)
my_custom_field, created = CustomField.objects.get_or_create(
type=CF_TYPE_TEXT,
name='my_custom_field',
description='My own custom field'
)
if created:
my_custom_field.obj_type.add(device)
my_custom_field.obj_type.add(device_type)
```
#### Initializers
Initializers are built-in startup scripts for defining NetBox custom fields, groups and users.
All you need to do is to mount you own `initializers` folder ([see `docker-compose.yml`][netbox-docker-compose]).
Look at the [`initializers` folder][netbox-docker-initializers] to learn how the files must look like.
Here's an example for defining a custom field:
```yaml
# initializers/custom_fields.yml
text_field:
type: text
label: Custom Text
description: Enter text in a text field.
required: false
filter_logic: loose
weight: 0
on_objects:
- dcim.models.Device
- dcim.models.Rack
- ipam.models.IPAddress
- ipam.models.Prefix
- tenancy.models.Tenant
- virtualization.models.VirtualMachine
```
[netbox-docker-initializers]: https://github.com/ninech/netbox-docker/tree/master/initializers
[netbox-docker-compose]: https://github.com/ninech/netbox-docker/blob/master/docker-compose.yml
#### Custom Docker Image
You can also build your own NetBox Docker image containing your own startup scripts, custom fields, users and groups
like this:
```
ARG VERSION=latest
FROM ninech/netbox:$VERSION
COPY startup_scripts/ /opt/netbox/startup_scripts/
COPY initializers/ /opt/netbox/initializers/
```
## Netbox Version
The `docker-compose.yml` file is prepared to run a specific version of NetBox.
To use this feature, set the environment-variable `VERSION` before launching `docker-compose`, as shown below.
The `docker-compose.yml` file is prepared to run a specific version of Netbox, instead of `latest`.
To use this feature, set and export the environment-variable `VERSION` before launching `docker-compose`, as shown below.
`VERSION` may be set to the name of
[any tag of the `ninech/netbox` Docker image on Docker Hub][netbox-dockerhub].
```
$ export VERSION=v2.2.6
$ docker-compose pull netbox
$ docker-compose up -d
```
You can also build a specific version of the NetBox image. This time, `VERSION` indicates any valid
[Git Reference][git-ref] declared on [the 'digitalocean/netbox' Github repository][netbox-github].
Most commonly you will specify a tag or branch name.
```
$ export VERSION=develop
$ docker-compose build --no-cache netbox
$ docker-compose up -d
```
Hint: If you're building a specific version by tag name, the `--no-cache` argument is not strictly necessary.
This can increase the build speed if you're just adjusting the config, for example.
[git-ref]: https://git-scm.com/book/en/v2/Git-Internals-Git-References
[netbox-github]: https://github.com/digitalocean/netbox/releases
### LDAP enabled variant
The images tagged with "-ldap" contain anything necessary to authenticate against an LDAP or Active Directory server.
The default configuration `ldap_config.py` is prepared for use with an Active Directory server.
Custom values can be injected using environment variables, similar to the main configuration mechanisms.
## Troubleshooting
This section is a collection of some common issues and how to resolve them.
If your issue is not here, look through [the existing issues][issues] and eventually create a new issue.
[issues]: (https://github.com/ninech/netbox-docker/issues)
### Docker Compose basics
* You can see all running containers belonging to this project using `docker-compose ps`.
* You can see the logs by running `docker-compose logs -f`.
Running `docker-compose logs -f netbox` will just show the logs for netbox.
* You can stop everything using `docker-compose stop`.
* You can clean up everything using `docker-compose down -v --remove-orphans`. **This will also remove any related data.**
* You can enter the shell of the running NetBox container using `docker-compose exec netbox /bin/bash`. Now you have access to `./manage.py`, e.g. to reset a password.
* To access the database run `docker-compose exec postgres sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'`
* To create a database backup run `docker-compose exec postgres sh -c 'pg_dump -cU $POSTGRES_USER $POSTGRES_DB' | gzip > db_dump.sql.gz`
* To restore that database backup run `gunzip -c db_dump.sql.gz | docker exec -i $(docker-compose ps -q postgres) sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'`.
### Getting a "Bad Request (400)"
> When connecting to the NetBox instance, I get a "Bad Request (400)" error.
This usually happens when the `ALLOWED_HOSTS` variable is not set correctly.
### How to upgrade
> How do I update to a newer version?
It should be sufficient to pull the latest image from Docker Hub, stopping the container and starting it up again:
[any tag of the `netboxcommunity/netbox` Docker image on Docker Hub][netbox-dockerhub].
```bash
export VERSION=v2.7.1
docker-compose pull netbox
docker-compose stop netbox
docker-compose rm -f netbox
docker-compose up -d netbox
docker-compose up -d
```
### Breaking Changes
From time to time it might become necessary to re-order the structure of the container.
Things like the `docker-compose.yml` file or your Kubernets or OpenShift configurations have to be adjusted as a consequence.
Since April 2018 each image built from this repo contains a `NETBOX_DOCKER_PROJECT_VERSION` label.
You can check the label of your local image by running `docker inspect ninech/netbox:v2.3.1 --format "{{json .ContainerConfig.Labels}}"`.
The following is a list of breaking changes:
* 0.3.0: Field `filterable: <boolean` was replaced with field `filter_logic: loose/exact/disabled`. It will default to `CF_FILTER_LOOSE=loose` when not defined.
* 0.2.0: Re-organized paths: `/etc/netbox -> /etc/netbox/config` and `/etc/reports -> /etc/netbox/reports`. Fixes [#54](https://github.com/ninech/netbox-docker/issues/54).
* 0.1.0: Introduction of the `NETBOX_DOCKER_PROJECT_VERSION`. (Not a breaking change per se.)
## Rebuilding & Publishing images
`./build.sh` is used to rebuild the Docker image:
You can also build a specific version of the Netbox Docker image yourself.
`VERSION` can be any valid [git ref][git-ref] in that case.
```bash
export VERSION=v2.7.1
./build.sh $VERSION
docker-compose up -d
```
$ ./build.sh --help
Usage: ./build.sh <branch> [--push]
branch The branch or tag to build. Required.
--push Pushes built Docker image to docker hub.
You can use the following ENV variables to customize the build:
BRANCH The branch to build.
Also used for tagging the image.
DOCKER_REPO The Docker registry (i.e. hub.docker.com/r/DOCKER_REPO/netbox)
Also used for tagging the image.
Default: ninech
SRC_REPO Which fork of netbox to use (i.e. github.com/<SRC_REPO>/netbox).
Default: digitalocean
URL Where to fetch the package from.
Must be a tar.gz file of the source code.
Default: https://github.com/${SRC_REPO}/netbox/archive/$BRANCH.tar.gz
```
[git-ref]: https://git-scm.com/book/en/v2/Git-Internals-Git-References
[netbox-github]: https://github.com/netbox-community/netbox/releases
## Breaking Changes
From time to time it might become necessary to re-engineer the structure of this setup.
Things like the `docker-compose.yml` file or your Kubernetes or OpenShift configurations have to be adjusted as a consequence.
Since November 2019 each image built from this repo contains a `org.opencontainers.image.version` label.
(The images contained labels since April 2018, although in November 2019 the labels' names changed.)
You can check the label of your local image by running `docker inspect netboxcommunity/netbox:v2.7.1 --format "{{json .Config.Labels}}"`.
Please read [the release notes][releases] carefully when updating to a new image version.
[releases]: https://github.com/netbox-community/netbox-docker/releases
## Rebuilding the Image
`./build.sh` can be used to rebuild the Docker image. See `./build.sh --help` for more information.
For more details on custom builds [consult our wiki][netbox-docker-wiki-build].
[netbox-docker-wiki-build]: https://github.com/netbox-community/netbox-docker/wiki/Build
## Tests
To run the test coming with NetBox, use the `docker-compose.yml` file as such:
We have a test script.
It runs Netbox's own unit tests and ensures that all initializers work:
```
$ docker-compose run netbox ./manage.py test
```bash
IMAGE=netboxcommunity/netbox:latest ./test.sh
```
## About
This repository is currently maintained and funded by [nine](https://nine.ch), your cloud navigator.
This repository is currently maintained and funded by [nxt][nxt].
[![logo of the company 'nine'](https://logo.apps.at-nine.ch/Dmqied_eSaoBMQwk3vVgn4UIgDo=/trim/500x0/logo_claim.png)](https://www.nine.ch)
[nxt]: https://nxt.engineering/en/

View File

@ -1 +1 @@
0.3.1
0.26.2

View File

@ -1,88 +0,0 @@
#!/bin/bash
# Builds all Docker images this project provides
# Arguments:
# BUILD: The release to build.
# Allowed: release, prerelease, branches, special
# Default: undefined
echo "▶️ $0 $*"
ALL_BUILDS=("release" "prerelease" "branches" "special")
BUILDS=("${BUILD:-"${ALL_BUILDS[@]}"}")
echo "⚙️ Configured builds: ${BUILDS[*]}"
VARIANTS=("" "ldap")
if [ ! -z "${DEBUG}" ]; then
export DEBUG
fi
ERROR=0
# Don't build if not on `master` and don't build if on a pull request,
# but build when DEBUG is not empty
if [ ! -z "${DEBUG}" ] || \
( [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] ); then
for VARIANT in "${VARIANTS[@]}"; do
export VARIANT
# Checking which VARIANT to build
if [ -z "$VARIANT" ]; then
DOCKERFILE="Dockerfile"
else
DOCKERFILE="Dockerfile.${VARIANT}"
# Fail fast
if [ ! -f "${DOCKERFILE}" ]; then
echo "🚨 The Dockerfile '${DOCKERFILE}' for variant '${VARIANT}' doesn't exist."
ERROR=1
if [ -z "$DEBUG" ]; then
continue
else
echo "⚠️ Would skip this, but DEBUG is enabled."
fi
fi
fi
for BUILD in "${BUILDS[@]}"; do
echo "🛠 Building '$BUILD' from '$DOCKERFILE'"
case $BUILD in
release)
# build the latest release
# shellcheck disable=SC2068
./build-latest.sh $@ || ERROR=1
;;
prerelease)
# build the latest pre-release
# shellcheck disable=SC2068
PRERELEASE=true ./build-latest.sh $@ || ERROR=1
;;
branches)
# build all branches
# shellcheck disable=SC2068
./build-branches.sh $@ || ERROR=1
;;
special)
# special build
# shellcheck disable=SC2068
#SRC_ORG=lampwins TAG=webhooks-backend ./build.sh "feature/webhooks-backend" $@ || ERROR=1
;;
*)
echo "🚨 Unrecognized build '$BUILD'."
if [ -z "$DEBUG" ]; then
exit 1
else
echo "⚠️ Would exit here with code '1', but DEBUG is enabled."
fi
;;
esac
done
done
else
echo "❎ Not building anything."
fi
exit $ERROR

View File

@ -1,20 +0,0 @@
#!/bin/bash
# Builds develop, develop-* and master branches
echo "▶️ $0 $*"
ORIGINAL_GITHUB_REPO="digitalocean/netbox"
GITHUB_REPO="${GITHUB_REPO-$ORIGINAL_GITHUB_REPO}"
URL_RELEASES="https://api.github.com/repos/${GITHUB_REPO}/branches"
CURL="curl -sS"
BRANCHES=$($CURL "${URL_RELEASES}" | jq -r 'map(.name) | .[] | scan("^[^v].+") | match("^(master|develop).*") | .string')
ERROR=0
for BRANCH in $BRANCHES; do
# shellcheck disable=SC2068
./build.sh "${BRANCH}" $@ || ERROR=1
done
exit $ERROR

View File

@ -0,0 +1,8 @@
#!/bin/bash
push_image_to_registry() {
local target_tag=$1
echo "⏫ Pushing '${target_tag}'"
$DRY docker push "${target_tag}"
echo "✅ Finished pushing the Docker image '${target_tag}'."
}

View File

@ -0,0 +1,82 @@
#!/bin/bash
# Retrieves image configuration from public images in DockerHub
# Functions from https://gist.github.com/cirocosta/17ea17be7ac11594cb0f290b0a3ac0d1
# Optimised for our use case
get_image_label() {
local label=$1
local image=$2
local tag=$3
local token
token=$(_get_token "$image")
local digest
digest=$(_get_digest "$image" "$tag" "$token")
local retval="null"
if [ "$digest" != "null" ]; then
retval=$(_get_image_configuration "$image" "$token" "$digest" "$label")
fi
echo "$retval"
}
get_image_layers() {
local image=$1
local tag=$2
local token
token=$(_get_token "$image")
_get_layers "$image" "$tag" "$token"
}
get_image_last_layer() {
local image=$1
local tag=$2
local token
token=$(_get_token "$image")
local layers
mapfile -t layers < <(_get_layers "$image" "$tag" "$token")
echo "${layers[-1]}"
}
_get_image_configuration() {
local image=$1
local token=$2
local digest=$3
local label=$4
curl \
--silent \
--location \
--header "Authorization: Bearer $token" \
"https://registry-1.docker.io/v2/$image/blobs/$digest" \
| jq -r ".config.Labels.\"$label\""
}
_get_token() {
local image=$1
curl \
--silent \
"https://auth.docker.io/token?scope=repository:$image:pull&service=registry.docker.io" \
| jq -r '.token'
}
_get_digest() {
local image=$1
local tag=$2
local token=$3
curl \
--silent \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--header "Authorization: Bearer $token" \
"https://registry-1.docker.io/v2/$image/manifests/$tag" \
| jq -r '.config.digest'
}
_get_layers() {
local image=$1
local tag=$2
local token=$3
curl \
--silent \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--header "Authorization: Bearer $token" \
"https://registry-1.docker.io/v2/$image/manifests/$tag" \
| jq -r '.layers[].digest'
}

View File

@ -3,17 +3,50 @@
echo "▶️ $0 $*"
ORIGINAL_GITHUB_REPO="digitalocean/netbox"
GITHUB_REPO="${GITHUB_REPO-$ORIGINAL_GITHUB_REPO}"
URL_RELEASES="https://api.github.com/repos/${GITHUB_REPO}/releases"
###
# 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
###
# Checking if PRERELEASE is either unset, 'true' or 'false'
###
if [ -n "${PRERELEASE}" ] &&
{ [ "${PRERELEASE}" != "true" ] && [ "${PRERELEASE}" != "false" ]; }; then
if [ -z "${DEBUG}" ]; then
echo "⚠️ PRERELEASE must be either unset, 'true' or 'false', but was '${PRERELEASE}'!"
exit 1
else
echo "⚠️ Would exit here with code '1', but DEBUG is enabled."
fi
fi
###
# Calling Github to get the latest version
###
ORIGINAL_GITHUB_REPO="netbox-community/netbox"
GITHUB_REPO="${GITHUB_REPO-$ORIGINAL_GITHUB_REPO}"
URL_RELEASES="https://api.github.com/repos/${GITHUB_REPO}/releases?${GITHUB_OAUTH_PARAMS}"
# Composing the JQ commans to extract the most recent version number
JQ_LATEST="group_by(.prerelease) | .[] | sort_by(.published_at) | reverse | .[0] | select(.prerelease==${PRERELEASE-false}) | .tag_name"
CURL="curl -sS"
# Querying the Github API to fetch the most recent version number
VERSION=$($CURL "${URL_RELEASES}" | jq -r "${JQ_LATEST}")
###
# Check if the prerelease version is actually higher than stable version
###
if [ "${PRERELEASE}" == "true" ]; then
JQ_STABLE="group_by(.prerelease) | .[] | sort_by(.published_at) | reverse | .[0] | select(.prerelease==false) | .tag_name"
STABLE_VERSION=$($CURL "${URL_RELEASES}" | jq -r "${JQ_STABLE}")
@ -27,10 +60,16 @@ if [ "${PRERELEASE}" == "true" ]; then
# shellcheck disable=SC2003
MINOR_UNSTABLE=$(expr match "${VERSION}" 'v[0-9]\+\.\([0-9]\+\)')
if ( [ "$MAJOR_STABLE" -eq "$MAJOR_UNSTABLE" ] && [ "$MINOR_STABLE" -ge "$MINOR_UNSTABLE" ] ) \
|| [ "$MAJOR_STABLE" -gt "$MAJOR_UNSTABLE" ]; then
echo "❎ Latest unstable version ('$VERSION') is not higher than the latest stable version ('$STABLE_VERSION')."
if { [ "${MAJOR_STABLE}" -eq "${MAJOR_UNSTABLE}" ] \
&& [ "${MINOR_STABLE}" -ge "${MINOR_UNSTABLE}" ];
} || [ "${MAJOR_STABLE}" -gt "${MAJOR_UNSTABLE}" ]; then
echo "❎ Latest unstable version '${VERSION}' is not higher than the latest stable version '$STABLE_VERSION'."
if [ -z "$DEBUG" ]; then
if [ -n "${GH_ACTION}" ]; then
echo "::set-output name=skipped::true"
fi
exit 0
else
echo "⚠️ Would exit here with code '0', but DEBUG is enabled."
@ -38,28 +77,6 @@ if [ "${PRERELEASE}" == "true" ]; then
fi
fi
# Check if that version is not already available on docker hub:
ORIGINAL_DOCKERHUB_REPO="ninech/netbox"
DOCKERHUB_REPO="${DOCKERHUB_REPO-$ORIGINAL_DOCKERHUB_REPO}"
URL_DOCKERHUB_TOKEN="https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_REPO}:pull"
BEARER_TOKEN="$($CURL "${URL_DOCKERHUB_TOKEN}" | jq -r .token)"
URL_DOCKERHUB_TAG="https://registry.hub.docker.com/v2/${DOCKERHUB_REPO}/tags/list"
AUTHORIZATION_HEADER="Authorization: Bearer ${BEARER_TOKEN}"
if [ -z "$VARIANT" ]; then
DOCKER_TAG="${VERSION}"
else
DOCKER_TAG="${VERSION}-${VARIANT}"
fi
ALREADY_BUILT="$($CURL -H "${AUTHORIZATION_HEADER}" "${URL_DOCKERHUB_TAG}" | jq -e ".tags | any(.==\"${DOCKER_TAG}\")")"
if [ "$ALREADY_BUILT" == "false" ]; then
# shellcheck disable=SC2068
./build.sh "${VERSION}" $@
exit $?
else
echo "${DOCKER_TAG} already exists on https://hub.docker.com/r/${DOCKERHUB_REPO}"
exit 0
fi
# shellcheck disable=SC2068
./build.sh "${VERSION}" $@
exit $?

39
build-next.sh Executable file
View File

@ -0,0 +1,39 @@
#!/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

457
build.sh
View File

@ -1,68 +1,92 @@
#!/bin/bash
# Builds the Dockerfile[.variant] and injects tgz'ed Netbox code from Github
# Clones the Netbox repository with git from Github and builds the Dockerfile
echo "▶️ $0 $*"
set -e
if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then
echo "Usage: ${0} <branch> [--push]"
echo " branch The branch or tag to build. Required."
echo " --push Pushes built Docker image to docker hub."
echo "Usage: ${0} <branch> [--push|--push-only]"
echo " branch The branch or tag to build. Required."
echo " --push Pushes the built Docker image to the registry."
echo " --push-only Only pushes the Docker image to the registry, but does not build it."
echo ""
echo "You can use the following ENV variables to customize the build:"
echo " DEBUG If defined, the script does not stop when certain checks are unsatisfied."
echo " DRY_RUN Prints all build statements instead of running them."
echo " DOCKER_OPTS Add parameters to Docker."
echo " Default:"
echo " When <TAG> starts with 'v': \"\""
echo " Else: \"--no-cache\""
echo " BRANCH The branch to build."
echo " Also used for tagging the image."
echo " TAG The version part of the docker tag."
echo " Default:"
echo " When <BRANCH>=master: latest"
echo " When <BRANCH>=develop: snapshot"
echo " Else: same as <BRANCH>"
echo " DOCKER_ORG The Docker registry (i.e. hub.docker.com/r/<DOCKER_ORG>/<DOCKER_REPO>) "
echo " Also used for tagging the image."
echo " Default: ninech"
echo " DOCKER_REPO The Docker registry (i.e. hub.docker.com/r/<DOCKER_ORG>/<DOCKER_REPO>) "
echo " Also used for tagging the image."
echo " Default: netbox"
echo " DOCKER_TAG The name of the tag which is applied to the image."
echo " Useful for pushing into another registry than hub.docker.com."
echo " Default: <DOCKER_ORG>/<DOCKER_REPO>:<BRANCH>"
echo " SRC_ORG Which fork of netbox to use (i.e. github.com/<SRC_ORG>/<SRC_REPO>)."
echo " Default: digitalocean"
echo " SRC_REPO The name of the netbox for to use (i.e. github.com/<SRC_ORG>/<SRC_REPO>)."
echo " Default: netbox"
echo " URL Where to fetch the package from."
echo " Must be a tar.gz file of the source code."
echo " Default: https://github.com/<SRC_ORG>/<SRC_REPO>/archive/\$BRANCH.tar.gz"
echo " VARIANT The variant to build."
echo " The value will be used as a suffix to the \$TAG and for the Dockerfile"
echo " selection. The TAG being build must exist for the base variant and"
echo " corresponding Dockerfile must start with the following lines:"
echo " ARG DOCKER_ORG=ninech"
echo " ARG DOCKER_REPO=netbox"
echo " ARG FROM_TAG=latest"
echo " FROM \$DOCKER_ORG/\$DOCKER_REPO:\$FROM_TAG"
echo " Example: VARIANT=ldap will result in the tag 'latest-ldap' and the"
echo " Dockerfile 'Dockerfile.ldap' being used."
echo " Default: empty"
echo " HTTP_PROXY The proxy to use for http requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty"
echo " HTTPS_PROXY The proxy to use for https requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty"
echo " FTP_PROXY The proxy to use for ftp requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty"
echo " NO_PROXY Comma-separated list of domain extensions proxy should not be used for."
echo " Example: .domain1.tld,.domain2.tld"
echo " Default: empty"
echo " SRC_ORG Which fork of netbox to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})."
echo " Default: netbox-community"
echo " SRC_REPO The name of the repository to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})."
echo " Default: netbox"
echo " URL Where to fetch the code from."
echo " Must be a git repository. Can be private."
echo " Default: https://github.com/\${SRC_ORG}/\${SRC_REPO}.git"
echo " NETBOX_PATH The path where netbox will be checkout out."
echo " Must not be outside of the netbox-docker repository (because of Docker)!"
echo " Default: .netbox"
echo " SKIP_GIT If defined, git is not invoked and \${NETBOX_PATH} will not be altered."
echo " This may be useful, if you are manually managing the NETBOX_PATH."
echo " Default: undefined"
echo " TAG The version part of the docker tag."
echo " Default:"
echo " When <branch>=master: latest"
echo " When <branch>=develop: snapshot"
echo " Else: same as <branch>"
echo " DOCKER_REGISTRY The Docker repository's registry (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')"
echo " Used for tagging the image."
echo " Default: docker.io"
echo " DOCKER_ORG The Docker repository's organisation (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')"
echo " Used for tagging the image."
echo " Default: netboxcommunity"
echo " DOCKER_REPO The Docker repository's name (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')"
echo " Used for tagging the image."
echo " Default: netbox"
echo " DOCKER_TAG The name of the tag which is applied to the image."
echo " Useful for pushing into another registry than hub.docker.com."
echo " Default: \${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:\${TAG}"
echo " DOCKER_SHORT_TAG The name of the short tag which is applied to the"
echo " image. This is used to tag all patch releases to their"
echo " containing version e.g. v2.5.1 -> v2.5"
echo " Default: \${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:<MAJOR>.<MINOR>"
echo " DOCKERFILE The name of Dockerfile to use."
echo " Default: Dockerfile"
echo " DOCKER_FROM The base image to use."
echo " Default: 'python:3.8-alpine'"
echo " DOCKER_TARGET A specific target to build."
echo " It's currently not possible to pass multiple targets."
echo " Default: main ldap"
echo " HTTP_PROXY The proxy to use for http requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: undefined"
echo " NO_PROXY Comma-separated list of domain extensions proxy should not be used for."
echo " Example: .domain1.tld,.domain2.tld"
echo " Default: undefined"
echo " DEBUG If defined, the script does not stop when certain checks are unsatisfied."
echo " Default: undefined"
echo " DRY_RUN Prints all build statements instead of running them."
echo " Default: undefined"
echo " GH_ACTION If defined, special 'echo' statements are enabled that set the"
echo " following environment variables in Github Actions:"
echo " - FINAL_DOCKER_TAG: The final value of the DOCKER_TAG env variable"
echo " Default: undefined"
echo ""
echo "Examples:"
echo " ${0} master"
echo " This will fetch the latest 'master' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:latest'."
echo " ${0} develop"
echo " This will fetch the latest 'develop' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:snapshot'."
echo " ${0} v2.6.6"
echo " This will fetch the 'v2.6.6' tag, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:v2.6.6' and 'netboxcommunity/netbox:v2.6'."
echo " ${0} develop-2.7"
echo " This will fetch the 'develop-2.7' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:develop-2.7'."
echo " SRC_ORG=cimnine ${0} feature-x"
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,"
echo " build a Docker Image and tag it 'netboxcommunity/netbox:feature-x'."
echo " SRC_ORG=cimnine DOCKER_ORG=cimnine ${0} feature-x"
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,"
echo " build a Docker Image and tag it 'cimnine/netbox:feature-x'."
if [ "${1}x" == "x" ]; then
exit 1
@ -71,93 +95,278 @@ if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then
fi
fi
# read the project version and trim it
# see https://stackoverflow.com/a/3232433/172132
NETBOX_DOCKER_PROJECT_VERSION="${NETBOX_DOCKER_PROJECT_VERSION-$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' VERSION)}"
###
# Enabling dry-run mode
###
if [ -z "${DRY_RUN}" ]; then
DRY=""
else
echo "⚠️ DRY_RUN MODE ON ⚠️"
DRY="echo"
fi
# variables for fetching the source
SRC_ORG="${SRC_ORG-digitalocean}"
###
# Variables for fetching the source
###
SRC_ORG="${SRC_ORG-netbox-community}"
SRC_REPO="${SRC_REPO-netbox}"
BRANCH="${1}"
URL="${URL-https://github.com/${SRC_ORG}/${SRC_REPO}/archive/$BRANCH.tar.gz}"
NETBOX_BRANCH="${1}"
URL="${URL-https://github.com/${SRC_ORG}/${SRC_REPO}.git}"
NETBOX_PATH="${NETBOX_PATH-.netbox}"
# variables for tagging the docker image
DOCKER_ORG="${DOCKER_ORG-ninech}"
###
# Fetching the source
###
if [ "${2}" != "--push-only" ] && [ -z "${SKIP_GIT}" ] ; then
echo "🌐 Checking out '${NETBOX_BRANCH}' of netbox from the url '${URL}' into '${NETBOX_PATH}'"
if [ ! -d "${NETBOX_PATH}" ]; then
$DRY git clone -q --depth 10 -b "${NETBOX_BRANCH}" "${URL}" "${NETBOX_PATH}"
fi
(
$DRY cd "${NETBOX_PATH}"
if [ -n "${HTTP_PROXY}" ]; then
git config http.proxy "${HTTP_PROXY}"
fi
$DRY git remote set-url origin "${URL}"
$DRY git fetch -qp --depth 10 origin "${NETBOX_BRANCH}"
$DRY git checkout -qf FETCH_HEAD
$DRY git prune
)
echo "✅ Checked out netbox"
fi
###
# Determining the value for DOCKERFILE
# and checking whether it exists
###
DOCKERFILE="${DOCKERFILE-Dockerfile}"
if [ ! -f "${DOCKERFILE}" ]; then
echo "🚨 The Dockerfile ${DOCKERFILE} doesn't exist."
if [ -z "${DEBUG}" ]; then
exit 1
else
echo "⚠️ Would exit here with code '1', but DEBUG is enabled."
fi
fi
###
# Determining the value for DOCKER_FROM
###
if [ -z "$DOCKER_FROM" ]; then
DOCKER_FROM="python:3.8-alpine"
fi
###
# Variables for labelling the docker image
###
BUILD_DATE="$(date -u '+%Y-%m-%dT%H:%M+00:00')"
if [ -d ".git" ]; then
GIT_REF="$(git rev-parse HEAD)"
fi
# Read the project version from the `VERSION` file and trim it, see https://stackoverflow.com/a/3232433/172132
PROJECT_VERSION="${PROJECT_VERSION-$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' VERSION)}"
# Get the Git information from the netbox directory
if [ -d "${NETBOX_PATH}/.git" ]; then
NETBOX_GIT_REF=$(cd "${NETBOX_PATH}"; git rev-parse HEAD)
NETBOX_GIT_BRANCH=$(cd "${NETBOX_PATH}"; git rev-parse --abbrev-ref HEAD)
NETBOX_GIT_URL=$(cd "${NETBOX_PATH}"; git remote get-url origin)
fi
###
# Variables for tagging the docker image
###
DOCKER_REGISTRY="${DOCKER_REGISTRY-docker.io}"
DOCKER_ORG="${DOCKER_ORG-netboxcommunity}"
DOCKER_REPO="${DOCKER_REPO-netbox}"
case "${BRANCH}" in
case "${NETBOX_BRANCH}" in
master)
TAG="${TAG-latest}";;
develop)
TAG="${TAG-snapshot}";;
*)
TAG="${TAG-$BRANCH}";;
TAG="${TAG-$NETBOX_BRANCH}";;
esac
DOCKER_TAG="${DOCKER_TAG-${DOCKER_ORG}/${DOCKER_REPO}:${TAG}}"
# Checking which VARIANT to build
if [ -z "$VARIANT" ]; then
DOCKERFILE="Dockerfile"
else
DOCKERFILE="Dockerfile.${VARIANT}"
DOCKER_TAG="${DOCKER_TAG}-${VARIANT}"
###
# Determine targets to build
###
DEFAULT_DOCKER_TARGETS=("main" "ldap")
DOCKER_TARGETS=( "${DOCKER_TARGET:-"${DEFAULT_DOCKER_TARGETS[@]}"}")
echo "🏭 Building the following targets:" "${DOCKER_TARGETS[@]}"
# Fail fast
if [ ! -f "${DOCKERFILE}" ]; then
echo "🚨 The Dockerfile ${DOCKERFILE} for variant '${VARIANT}' doesn't exist."
###
# Build each target
###
export DOCKER_BUILDKIT=${DOCKER_BUILDKIT-1}
for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
echo "🏗 Building the target '${DOCKER_TARGET}'"
if [ -z "$DEBUG" ]; then
exit 1
else
echo "⚠️ Would exit here with code '1', but DEBUG is enabled."
###
# composing the final TARGET_DOCKER_TAG
###
TARGET_DOCKER_TAG="${DOCKER_TAG-${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:${TAG}}"
if [ "${DOCKER_TARGET}" != "main" ]; then
TARGET_DOCKER_TAG="${TARGET_DOCKER_TAG}-${DOCKER_TARGET}"
fi
if [ -n "${GH_ACTION}" ]; then
echo "FINAL_DOCKER_TAG=${TARGET_DOCKER_TAG}" >> $GITHUB_ENV
echo "::set-output name=skipped::false"
fi
###
# composing the additional DOCKER_SHORT_TAG,
# i.e. "v2.6.1" becomes "v2.6",
# which is only relevant for version tags
# Also let "latest" follow the highest version
###
if [[ "${TAG}" =~ ^v([0-9]+)\.([0-9]+)\.[0-9]+$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
TARGET_DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:v${MAJOR}.${MINOR}}"
TARGET_DOCKER_LATEST_TAG="${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:latest"
if [ "${DOCKER_TARGET}" != "main" ]; then
TARGET_DOCKER_SHORT_TAG="${TARGET_DOCKER_SHORT_TAG}-${DOCKER_TARGET}"
TARGET_DOCKER_LATEST_TAG="${TARGET_DOCKER_LATEST_TAG}-${DOCKER_TARGET}"
fi
fi
fi
DOCKER_OPTS=("${DOCKER_OPTS[@]}")
###
# Proceeding to buils stage, except if `--push-only` is passed
###
if [ "${2}" != "--push-only" ] ; then
###
# Checking if the build is necessary,
# meaning build only if one of those values changed:
# - Python base image digest (Label: PYTHON_BASE_DIGEST)
# - netbox git ref (Label: NETBOX_GIT_REF)
# - netbox-docker git ref (Label: org.label-schema.vcs-ref)
###
# Load information from registry (only for docker.io)
SHOULD_BUILD="false"
BUILD_REASON=""
if [ -z "${GH_ACTION}" ]; then
# Asuming non Github builds should always proceed
SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} interactive"
elif [ "$DOCKER_REGISTRY" = "docker.io" ]; then
source ./build-functions/get-public-image-config.sh
IFS=':' read -ra DOCKER_FROM_SPLIT <<< "${DOCKER_FROM}"
if ! [[ ${DOCKER_FROM_SPLIT[0]} =~ .*/.* ]]; then
# Need to use "library/..." for images the have no two part name
DOCKER_FROM_SPLIT[0]="library/${DOCKER_FROM_SPLIT[0]}"
fi
PYTHON_LAST_LAYER=$(get_image_last_layer "${DOCKER_FROM_SPLIT[0]}" "${DOCKER_FROM_SPLIT[1]}")
mapfile -t IMAGES_LAYERS_OLD < <(get_image_layers "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}")
NETBOX_GIT_REF_OLD=$(get_image_label NETBOX_GIT_REF "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}")
GIT_REF_OLD=$(get_image_label org.label-schema.vcs-ref "${DOCKER_ORG}"/"${DOCKER_REPO}" "${TAG}")
# caching is only ok for version tags
case "${TAG}" in
v*) ;;
*) DOCKER_OPTS+=( "--no-cache" ) ;;
esac
if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${PYTHON_LAST_LAYER}\$"; then
SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} python"
fi
if [ "${NETBOX_GIT_REF}" != "${NETBOX_GIT_REF_OLD}" ]; then
SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} netbox"
fi
if [ "${GIT_REF}" != "${GIT_REF_OLD}" ]; then
SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} netbox-docker"
fi
else
SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} no-check"
fi
###
# Composing all arguments for `docker build`
###
DOCKER_BUILD_ARGS=(
--pull
--target "${DOCKER_TARGET}"
-f "${DOCKERFILE}"
-t "${TARGET_DOCKER_TAG}"
)
if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then
DOCKER_BUILD_ARGS+=( -t "${TARGET_DOCKER_SHORT_TAG}" )
DOCKER_BUILD_ARGS+=( -t "${TARGET_DOCKER_LATEST_TAG}" )
fi
DOCKER_OPTS+=( "--pull" )
# --label
DOCKER_BUILD_ARGS+=(
--label "ORIGINAL_TAG=${TARGET_DOCKER_TAG}"
# Build args
DOCKER_BUILD_ARGS=(
--build-arg "NETBOX_DOCKER_PROJECT_VERSION=${NETBOX_DOCKER_PROJECT_VERSION}"
--build-arg "FROM_TAG=${TAG}"
--build-arg "BRANCH=${BRANCH}"
--build-arg "URL=${URL}"
--build-arg "DOCKER_ORG=${DOCKER_ORG}"
--build-arg "DOCKER_REPO=${DOCKER_REPO}"
)
if [ -n "$HTTP_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "http_proxy=${HTTP_PROXY}" )
fi
if [ -n "$HTTPS_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "https_proxy=${HTTPS_PROXY}" )
fi
if [ -n "$FTP_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "ftp_proxy=${FTP_PROXY}" )
fi
if [ -n "$NO_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "no_proxy=${NO_PROXY}" )
fi
--label "org.label-schema.build-date=${BUILD_DATE}"
--label "org.opencontainers.image.created=${BUILD_DATE}"
if [ -z "$DRY_RUN" ]; then
DOCKER_CMD="docker"
else
echo "⚠️ DRY_RUN MODE ON ⚠️"
DOCKER_CMD="echo docker"
fi
--label "org.label-schema.version=${PROJECT_VERSION}"
--label "org.opencontainers.image.version=${PROJECT_VERSION}"
)
if [ -d ".git" ]; then
DOCKER_BUILD_ARGS+=(
--label "org.label-schema.vcs-ref=${GIT_REF}"
--label "org.opencontainers.image.revision=${GIT_REF}"
)
fi
if [ -d "${NETBOX_PATH}/.git" ]; then
DOCKER_BUILD_ARGS+=(
--label "NETBOX_GIT_BRANCH=${NETBOX_GIT_BRANCH}"
--label "NETBOX_GIT_REF=${NETBOX_GIT_REF}"
--label "NETBOX_GIT_URL=${NETBOX_GIT_URL}"
)
fi
if [ -n "${BUILD_REASON}" ]; then
BUILD_REASON=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "$BUILD_REASON")
DOCKER_BUILD_ARGS+=( --label "BUILD_REASON=${BUILD_REASON}" )
fi
echo "🐳 Building the Docker image '${DOCKER_TAG}' from the url '${URL}'."
$DOCKER_CMD build -t "${DOCKER_TAG}" "${DOCKER_BUILD_ARGS[@]}" "${DOCKER_OPTS[@]}" -f "${DOCKERFILE}" .
echo "✅ Finished building the Docker images '${DOCKER_TAG}'"
# --build-arg
DOCKER_BUILD_ARGS+=( --build-arg "NETBOX_PATH=${NETBOX_PATH}" )
if [ "${2}" == "--push" ] ; then
echo "⏫ Pushing '${DOCKER_TAG}"
$DOCKER_CMD push "${DOCKER_TAG}"
echo "✅ Finished pushing the Docker image '${DOCKER_TAG}'."
fi
if [ -n "${DOCKER_FROM}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "FROM=${DOCKER_FROM}" )
fi
if [ -n "${HTTP_PROXY}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "http_proxy=${HTTP_PROXY}" )
DOCKER_BUILD_ARGS+=( --build-arg "https_proxy=${HTTPS_PROXY}" )
fi
if [ -n "${NO_PROXY}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "no_proxy=${NO_PROXY}" )
fi
###
# Building the docker image
###
if [ "${SHOULD_BUILD}" == "true" ]; then
echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG}'."
echo " Build reason set to: ${BUILD_REASON}"
$DRY docker build "${DOCKER_BUILD_ARGS[@]}" .
echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG}'"
echo "🔎 Inspecting labels on '${TARGET_DOCKER_TAG}'"
$DRY docker inspect "${TARGET_DOCKER_TAG}" --format "{{json .Config.Labels}}"
else
echo "Build skipped because sources didn't change"
echo "::set-output name=skipped::true"
fi
fi
###
# Pushing the docker images if either `--push` or `--push-only` are passed
###
if [ "${2}" == "--push" ] || [ "${2}" == "--push-only" ] ; then
source ./build-functions/docker-functions.sh
push_image_to_registry "${TARGET_DOCKER_TAG}"
if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then
push_image_to_registry "${TARGET_DOCKER_SHORT_TAG}"
push_image_to_registry "${TARGET_DOCKER_LATEST_TAG}"
fi
fi
done

View File

@ -1,20 +1,28 @@
import os
import socket
####
## We recommend to not edit this file.
## Create separate files to overwrite the settings.
## See `extra.py` as an example.
####
# For reference see http://netbox.readthedocs.io/en/latest/configuration/mandatory-settings/
# Based on https://github.com/digitalocean/netbox/blob/develop/netbox/netbox/configuration.example.py
import re
from os.path import dirname, abspath, join
from os import environ
# For reference see https://netbox.readthedocs.io/en/stable/configuration/
# Based on https://github.com/netbox-community/netbox/blob/master/netbox/netbox/configuration.example.py
# Read secret from file
def read_secret(secret_name):
def _read_secret(secret_name, default = None):
try:
f = open('/run/secrets/' + secret_name, 'r', encoding='utf-8')
except EnvironmentError:
return ''
return default
else:
with f:
return f.readline().strip()
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_BASE_DIR = dirname(dirname(abspath(__file__)))
#########################
# #
@ -26,23 +34,49 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name.
#
# Example: ALLOWED_HOSTS = ['netbox.example.com', 'netbox.internal.local']
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(' ')
ALLOWED_HOSTS = environ.get('ALLOWED_HOSTS', '*').split(' ')
# PostgreSQL database configuration.
# PostgreSQL database configuration. See the Django documentation for a complete list of available parameters:
# https://docs.djangoproject.com/en/stable/ref/settings/#databases
DATABASE = {
'NAME': os.environ.get('DB_NAME', 'netbox'), # Database name
'USER': os.environ.get('DB_USER', ''), # PostgreSQL username
'PASSWORD': os.environ.get('DB_PASSWORD', read_secret('db_password')),
'NAME': environ.get('DB_NAME', 'netbox'), # Database name
'USER': environ.get('DB_USER', ''), # PostgreSQL username
'PASSWORD': _read_secret('db_password', environ.get('DB_PASSWORD', '')),
# PostgreSQL password
'HOST': os.environ.get('DB_HOST', 'localhost'), # Database server
'PORT': os.environ.get('DB_PORT', ''), # Database port (leave blank for default)
'HOST': environ.get('DB_HOST', 'localhost'), # Database server
'PORT': environ.get('DB_PORT', ''), # Database port (leave blank for default)
'OPTIONS': {'sslmode': environ.get('DB_SSLMODE', 'prefer')},
# Database connection SSLMODE
'CONN_MAX_AGE': int(environ.get('DB_CONN_MAX_AGE', '300')),
# Max database connection age
}
# Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
# configuration exists for each. Full connection details are required in both sections, and it is strongly recommended
# to use two separate database IDs.
REDIS = {
'tasks': {
'HOST': environ.get('REDIS_HOST', 'localhost'),
'PORT': int(environ.get('REDIS_PORT', 6379)),
'PASSWORD': _read_secret('redis_password', environ.get('REDIS_PASSWORD', '')),
'DATABASE': int(environ.get('REDIS_DATABASE', 0)),
'SSL': environ.get('REDIS_SSL', 'False').lower() == 'true',
},
'caching': {
'HOST': environ.get('REDIS_CACHE_HOST', environ.get('REDIS_HOST', 'localhost')),
'PORT': int(environ.get('REDIS_CACHE_PORT', environ.get('REDIS_PORT', 6379))),
'PASSWORD': _read_secret('redis_cache_password', environ.get('REDIS_CACHE_PASSWORD', environ.get('REDIS_PASSWORD', ''))),
'DATABASE': int(environ.get('REDIS_CACHE_DATABASE', 1)),
'SSL': environ.get('REDIS_CACHE_SSL', environ.get('REDIS_SSL', 'False')).lower() == 'true',
},
}
# This key is used for secure generation of random numbers and strings. It must never be exposed outside of this file.
# For optimal security, SECRET_KEY should be at least 50 characters in length and contain a mix of letters, numbers, and
# symbols. NetBox will not run without this defined. For more information, see
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY
SECRET_KEY = os.environ.get('SECRET_KEY', read_secret('secret_key'))
# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY
SECRET_KEY = _read_secret('secret_key', environ.get('SECRET_KEY', ''))
#########################
# #
@ -56,101 +90,159 @@ ADMINS = [
# ['John Doe', 'jdoe@example.com'],
]
# URL schemes that are allowed within links in NetBox
ALLOWED_URL_SCHEMES = (
'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc', 'xmpp',
)
# Optionally display a persistent banner at the top and/or bottom of every page. HTML is allowed. To display the same
# content in both banners, define BANNER_TOP and set BANNER_BOTTOM = BANNER_TOP.
BANNER_TOP = os.environ.get('BANNER_TOP', '')
BANNER_BOTTOM = os.environ.get('BANNER_BOTTOM', '')
BANNER_TOP = environ.get('BANNER_TOP', '')
BANNER_BOTTOM = environ.get('BANNER_BOTTOM', '')
# Text to include on the login page above the login form. HTML is allowed.
BANNER_LOGIN = os.environ.get('BANNER_LOGIN', '')
BANNER_LOGIN = environ.get('BANNER_LOGIN', '')
# Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set:
# BASE_PATH = 'netbox/'
BASE_PATH = os.environ.get('BASE_PATH', '')
BASE_PATH = environ.get('BASE_PATH', '')
# Cache timeout in seconds. Set to 0 to dissable caching. Defaults to 900 (15 minutes)
CACHE_TIMEOUT = int(environ.get('CACHE_TIMEOUT', 900))
# Maximum number of days to retain logged changes. Set to 0 to retain changes indefinitely. (Default: 90)
CHANGELOG_RETENTION = int(environ.get('CHANGELOG_RETENTION', 90))
# API Cross-Origin Resource Sharing (CORS) settings. If CORS_ORIGIN_ALLOW_ALL is set to True, all origins will be
# allowed. Otherwise, define a list of allowed origins using either CORS_ORIGIN_WHITELIST or
# CORS_ORIGIN_REGEX_WHITELIST. For more information, see https://github.com/ottoyiu/django-cors-headers
CORS_ORIGIN_ALLOW_ALL = os.environ.get('CORS_ORIGIN_ALLOW_ALL', 'False').lower() == 'true'
CORS_ORIGIN_WHITELIST = os.environ.get('CORS_ORIGIN_WHITELIST', '').split(' ')
CORS_ORIGIN_REGEX_WHITELIST = [
# r'^(https?://)?(\w+\.)?example\.com$',
]
CORS_ORIGIN_ALLOW_ALL = environ.get('CORS_ORIGIN_ALLOW_ALL', 'False').lower() == 'true'
CORS_ORIGIN_WHITELIST = list(filter(None, environ.get('CORS_ORIGIN_WHITELIST', 'https://localhost').split(' ')))
CORS_ORIGIN_REGEX_WHITELIST = [re.compile(r) for r in list(filter(None, environ.get('CORS_ORIGIN_REGEX_WHITELIST', '').split(' ')))]
# Set to True to enable server debugging. WARNING: Debugging introduces a substantial performance penalty and may reveal
# sensitive information about your installation. Only enable debugging while performing testing. Never enable debugging
# on a production system.
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
DEBUG = environ.get('DEBUG', 'False').lower() == 'true'
# Email settings
EMAIL = {
'SERVER': os.environ.get('EMAIL_SERVER', 'localhost'),
'PORT': int(os.environ.get('EMAIL_PORT', 25)),
'USERNAME': os.environ.get('EMAIL_USERNAME', ''),
'PASSWORD': os.environ.get('EMAIL_PASSWORD', read_secret('email_password')),
'TIMEOUT': int(os.environ.get('EMAIL_TIMEOUT', 10)), # seconds
'FROM_EMAIL': os.environ.get('EMAIL_FROM', ''),
'SERVER': environ.get('EMAIL_SERVER', 'localhost'),
'PORT': int(environ.get('EMAIL_PORT', 25)),
'USERNAME': environ.get('EMAIL_USERNAME', ''),
'PASSWORD': _read_secret('email_password', environ.get('EMAIL_PASSWORD', '')),
'USE_SSL': environ.get('EMAIL_USE_SSL', 'False').lower() == 'true',
'USE_TLS': environ.get('EMAIL_USE_TLS', 'False').lower() == 'true',
'SSL_CERTFILE': environ.get('EMAIL_SSL_CERTFILE', ''),
'SSL_KEYFILE': environ.get('EMAIL_SSL_KEYFILE', ''),
'TIMEOUT': int(environ.get('EMAIL_TIMEOUT', 10)), # seconds
'FROM_EMAIL': environ.get('EMAIL_FROM', ''),
}
# Enforcement of unique IP space can be toggled on a per-VRF basis.
# To enforce unique IP space within the global table (all prefixes and IP addresses not assigned to a VRF),
# set ENFORCE_GLOBAL_UNIQUE to True.
ENFORCE_GLOBAL_UNIQUE = os.environ.get('ENFORCE_GLOBAL_UNIQUE', 'False').lower() == 'true'
# Enforcement of unique IP space can be toggled on a per-VRF basis. To enforce unique IP space within the global table
# (all prefixes and IP addresses not assigned to a VRF), set ENFORCE_GLOBAL_UNIQUE to True.
ENFORCE_GLOBAL_UNIQUE = environ.get('ENFORCE_GLOBAL_UNIQUE', 'False').lower() == 'true'
# Exempt certain models from the enforcement of view permissions. Models listed here will be viewable by all users and
# by anonymous users. List models in the form `<app>.<model>`. Add '*' to this list to exempt all models.
EXEMPT_VIEW_PERMISSIONS = list(filter(None, environ.get('EXEMPT_VIEW_PERMISSIONS', '').split(' ')))
# Enable custom logging. Please see the Django documentation for detailed guidance on configuring custom logs:
# https://docs.djangoproject.com/en/1.11/topics/logging/
# https://docs.djangoproject.com/en/stable/topics/logging/
LOGGING = {}
# Setting this to True will permit only authenticated users to access any part of NetBox. By default, anonymous users
# are permitted to access most data in NetBox (excluding secrets) but not make any changes.
LOGIN_REQUIRED = os.environ.get('LOGIN_REQUIRED', 'False').lower() == 'true'
LOGIN_REQUIRED = environ.get('LOGIN_REQUIRED', 'False').lower() == 'true'
# Base URL path if accessing NetBox within a directory. For example, if installed at http://example.com/netbox/, set:
# BASE_PATH = 'netbox/'
BASE_PATH = os.environ.get('BASE_PATH', '')
# The length of time (in seconds) for which a user will remain logged into the web UI before being prompted to
# re-authenticate. (Default: 1209600 [14 days])
LOGIN_TIMEOUT = environ.get('LOGIN_TIMEOUT', None)
# Setting this to True will display a "maintenance mode" banner at the top of every page.
MAINTENANCE_MODE = os.environ.get('MAINTENANCE_MODE', 'False').lower() == 'true'
MAINTENANCE_MODE = environ.get('MAINTENANCE_MODE', 'False').lower() == 'true'
# An API consumer can request an arbitrary number of objects =by appending the "limit" parameter to the URL (e.g.
# "?limit=1000"). This setting defines the maximum limit. Setting it to 0 or None will allow an API consumer to request
# all objects by specifying "?limit=0".
MAX_PAGE_SIZE = int(os.environ.get('MAX_PAGE_SIZE', 1000))
MAX_PAGE_SIZE = int(environ.get('MAX_PAGE_SIZE', 1000))
# The file path where uploaded media such as image attachments are stored. A trailing slash is not needed. Note that
# the default value of this setting is derived from the installed location.
MEDIA_ROOT = os.environ.get('MEDIA_ROOT', os.path.join(BASE_DIR, 'media'))
MEDIA_ROOT = environ.get('MEDIA_ROOT', join(_BASE_DIR, 'media'))
# Credentials that NetBox will use to access live devices.
NAPALM_USERNAME = os.environ.get('NAPALM_USERNAME', '')
NAPALM_PASSWORD = os.environ.get('NAPALM_PASSWORD', read_secret('napalm_password'))
# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics'
METRICS_ENABLED = environ.get('METRICS_ENABLED', 'False').lower() == 'true'
# Credentials that NetBox will uses to authenticate to devices when connecting via NAPALM.
NAPALM_USERNAME = environ.get('NAPALM_USERNAME', '')
NAPALM_PASSWORD = _read_secret('napalm_password', environ.get('NAPALM_PASSWORD', ''))
# NAPALM timeout (in seconds). (Default: 30)
NAPALM_TIMEOUT = int(os.environ.get('NAPALM_TIMEOUT', 30))
NAPALM_TIMEOUT = int(environ.get('NAPALM_TIMEOUT', 30))
# NAPALM optional arguments (see http://napalm.readthedocs.io/en/latest/support/#optional-arguments). Arguments must
# be provided as a dictionary.
NAPALM_ARGS = {}
# Determine how many objects to display per page within a list. (Default: 50)
PAGINATE_COUNT = int(os.environ.get('PAGINATE_COUNT', 50))
PAGINATE_COUNT = int(environ.get('PAGINATE_COUNT', 50))
# Enable installed plugins. Add the name of each plugin to the list.
PLUGINS = []
# Plugins configuration settings. These settings are used by various plugins that the user may have installed.
# Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
PLUGINS_CONFIG = {
}
# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
# prefer IPv4 instead.
PREFER_IPV4 = os.environ.get('PREFER_IPV4', 'False').lower() == 'true'
PREFER_IPV4 = environ.get('PREFER_IPV4', 'False').lower() == 'true'
# Rack elevation size defaults, in pixels. For best results, the ratio of width to height should be roughly 10:1.
RACK_ELEVATION_DEFAULT_UNIT_HEIGHT = int(environ.get('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 22))
RACK_ELEVATION_DEFAULT_UNIT_WIDTH = int(environ.get('RACK_ELEVATION_DEFAULT_UNIT_WIDTH', 220))
# Remote authentication support
REMOTE_AUTH_ENABLED = environ.get('REMOTE_AUTH_ENABLED', 'False').lower() == 'true'
REMOTE_AUTH_BACKEND = environ.get('REMOTE_AUTH_BACKEND', 'netbox.authentication.RemoteUserBackend')
REMOTE_AUTH_HEADER = environ.get('REMOTE_AUTH_HEADER', 'HTTP_REMOTE_USER')
REMOTE_AUTH_AUTO_CREATE_USER = environ.get('REMOTE_AUTH_AUTO_CREATE_USER', 'True').lower() == 'true'
REMOTE_AUTH_DEFAULT_GROUPS = list(filter(None, environ.get('REMOTE_AUTH_DEFAULT_GROUPS', '').split(' ')))
# This determines how often the GitHub API is called to check the latest release of NetBox. Must be at least 1 hour.
RELEASE_CHECK_TIMEOUT = int(environ.get('RELEASE_CHECK_TIMEOUT', 24 * 3600))
# This repository is used to check whether there is a new release of NetBox available. Set to None to disable the
# version check or use the URL below to check for release in the official NetBox repository.
# https://api.github.com/repos/netbox-community/netbox/releases
RELEASE_CHECK_URL = environ.get('RELEASE_CHECK_URL', None)
# The file path where custom reports will be stored. A trailing slash is not needed. Note that the default value of
# this setting is derived from the installed location.
REPORTS_ROOT = os.environ.get('REPORTS_ROOT', '/etc/netbox/reports')
REPORTS_ROOT = environ.get('REPORTS_ROOT', '/etc/netbox/reports')
# Maximum execution time for background tasks, in seconds.
RQ_DEFAULT_TIMEOUT = int(environ.get('RQ_DEFAULT_TIMEOUT', 300))
# The file path where custom scripts will be stored. A trailing slash is not needed. Note that the default value of
# this setting is derived from the installed location.
SCRIPTS_ROOT = environ.get('SCRIPTS_ROOT', '/etc/netbox/scripts')
# By default, NetBox will store session data in the database. Alternatively, a file path can be specified here to use
# local file storage instead. (This can be useful for enabling authentication on a standby instance with read-only
# database access.) Note that the user as which NetBox runs must have read and write permissions to this path.
SESSION_FILE_PATH = environ.get('REPORTS_ROOT', None)
# Time zone (default: UTC)
TIME_ZONE = os.environ.get('TIME_ZONE', 'UTC')
TIME_ZONE = environ.get('TIME_ZONE', 'UTC')
# Date/time formatting. See the following link for supported formats:
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
DATE_FORMAT = os.environ.get('DATE_FORMAT', 'N j, Y')
SHORT_DATE_FORMAT = os.environ.get('SHORT_DATE_FORMAT', 'Y-m-d')
TIME_FORMAT = os.environ.get('TIME_FORMAT', 'g:i a')
SHORT_TIME_FORMAT = os.environ.get('SHORT_TIME_FORMAT', 'H:i:s')
DATETIME_FORMAT = os.environ.get('DATETIME_FORMAT', 'N j, Y g:i a')
SHORT_DATETIME_FORMAT = os.environ.get('SHORT_DATETIME_FORMAT', 'Y-m-d H:i')
# https://docs.djangoproject.com/en/stable/ref/templates/builtins/#date
DATE_FORMAT = environ.get('DATE_FORMAT', 'N j, Y')
SHORT_DATE_FORMAT = environ.get('SHORT_DATE_FORMAT', 'Y-m-d')
TIME_FORMAT = environ.get('TIME_FORMAT', 'g:i a')
SHORT_TIME_FORMAT = environ.get('SHORT_TIME_FORMAT', 'H:i:s')
DATETIME_FORMAT = environ.get('DATETIME_FORMAT', 'N j, Y g:i a')
SHORT_DATETIME_FORMAT = environ.get('SHORT_DATETIME_FORMAT', 'Y-m-d H:i')

55
configuration/extra.py Normal file
View File

@ -0,0 +1,55 @@
####
## This file contains extra configuration options that can't be configured
## directly through environment variables.
####
## Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of
## application errors (assuming correct email settings are provided).
# ADMINS = [
# # ['John Doe', 'jdoe@example.com'],
# ]
## URL schemes that are allowed within links in NetBox
# ALLOWED_URL_SCHEMES = (
# 'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc', 'xmpp',
# )
## NAPALM optional arguments (see http://napalm.readthedocs.io/en/latest/support/#optional-arguments). Arguments must
## be provided as a dictionary.
# NAPALM_ARGS = {}
## Enable installed plugins. Add the name of each plugin to the list.
# from netbox.configuration.configuration import PLUGINS
# PLUGINS.append('my_plugin')
## Plugins configuration settings. These settings are used by various plugins that the user may have installed.
## Each key in the dictionary is the name of an installed plugin and its value is a dictionary of settings.
# from netbox.configuration.configuration import PLUGINS_CONFIG
# PLUGINS_CONFIG['my_plugin'] = {
# 'foo': 'bar',
# 'buzz': 'bazz'
# }
## Remote authentication support
# REMOTE_AUTH_DEFAULT_PERMISSIONS = {}
## By default uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
## class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
# STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'
# STORAGE_CONFIG = {
# 'AWS_ACCESS_KEY_ID': 'Key ID',
# 'AWS_SECRET_ACCESS_KEY': 'Secret',
# 'AWS_STORAGE_BUCKET_NAME': 'netbox',
# 'AWS_S3_REGION_NAME': 'eu-west-1',
# }
## This file can contain arbitrary Python code, e.g.:
# from datetime import datetime
# now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
# BANNER_TOP = f'<marquee width="200px">This instance started on {now}.</marquee>'

View File

@ -0,0 +1,84 @@
import ldap
from django_auth_ldap.config import LDAPSearch
from importlib import import_module
from os import environ
# Read secret from file
def _read_secret(secret_name, default=None):
try:
f = open('/run/secrets/' + secret_name, 'r', encoding='utf-8')
except EnvironmentError:
return default
else:
with f:
return f.readline().strip()
# Import and return the group type based on string name
def _import_group_type(group_type_name):
mod = import_module('django_auth_ldap.config')
try:
return getattr(mod, group_type_name)()
except:
return None
# Server URI
AUTH_LDAP_SERVER_URI = environ.get('AUTH_LDAP_SERVER_URI', '')
# The following may be needed if you are binding to Active Directory.
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_REFERRALS: 0
}
# Set the DN and password for the NetBox service account.
AUTH_LDAP_BIND_DN = environ.get('AUTH_LDAP_BIND_DN', '')
AUTH_LDAP_BIND_PASSWORD = _read_secret('auth_ldap_bind_password', environ.get('AUTH_LDAP_BIND_PASSWORD', ''))
# Set a string template that describes any users distinguished name based on the username.
AUTH_LDAP_USER_DN_TEMPLATE = environ.get('AUTH_LDAP_USER_DN_TEMPLATE', None)
# Enable STARTTLS for ldap authentication.
AUTH_LDAP_START_TLS = environ.get('AUTH_LDAP_START_TLS', 'False').lower() == 'true'
# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert.
# Note that this is a NetBox-specific setting which sets:
# ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
LDAP_IGNORE_CERT_ERRORS = environ.get('LDAP_IGNORE_CERT_ERRORS', 'False').lower() == 'true'
AUTH_LDAP_USER_SEARCH_BASEDN = environ.get('AUTH_LDAP_USER_SEARCH_BASEDN', '')
AUTH_LDAP_USER_SEARCH_ATTR = environ.get('AUTH_LDAP_USER_SEARCH_ATTR', 'sAMAccountName')
AUTH_LDAP_USER_SEARCH = LDAPSearch(AUTH_LDAP_USER_SEARCH_BASEDN,
ldap.SCOPE_SUBTREE,
"(" + AUTH_LDAP_USER_SEARCH_ATTR + "=%(user)s)")
# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group
# heirarchy.
AUTH_LDAP_GROUP_SEARCH_BASEDN = environ.get('AUTH_LDAP_GROUP_SEARCH_BASEDN', '')
AUTH_LDAP_GROUP_SEARCH_CLASS = environ.get('AUTH_LDAP_GROUP_SEARCH_CLASS', 'group')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(AUTH_LDAP_GROUP_SEARCH_BASEDN, ldap.SCOPE_SUBTREE,
"(objectClass=" + AUTH_LDAP_GROUP_SEARCH_CLASS + ")")
AUTH_LDAP_GROUP_TYPE = _import_group_type(environ.get('AUTH_LDAP_GROUP_TYPE', 'GroupOfNamesType'))
# Define a group required to login.
AUTH_LDAP_REQUIRE_GROUP = environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', '')
# Define special user types using groups. Exercise great caution when assigning superuser status.
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_active": environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', ''),
"is_staff": environ.get('AUTH_LDAP_IS_ADMIN_DN', ''),
"is_superuser": environ.get('AUTH_LDAP_IS_SUPERUSER_DN', '')
}
# 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'
# Cache groups for one hour to reduce LDAP traffic
AUTH_LDAP_CACHE_TIMEOUT = int(environ.get('AUTH_LDAP_CACHE_TIMEOUT', 3600))
# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": environ.get('AUTH_LDAP_ATTR_FIRSTNAME', 'givenName'),
"last_name": environ.get('AUTH_LDAP_ATTR_LASTNAME', 'sn'),
"email": environ.get('AUTH_LDAP_ATTR_MAIL', 'mail')
}

View File

@ -1,58 +0,0 @@
import ldap
import os
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
# Server URI
AUTH_LDAP_SERVER_URI = os.environ.get('AUTH_LDAP_SERVER_URI', '')
# The following may be needed if you are binding to Active Directory.
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_REFERRALS: 0
}
# Set the DN and password for the NetBox service account.
AUTH_LDAP_BIND_DN = os.environ.get('AUTH_LDAP_BIND_DN', '')
AUTH_LDAP_BIND_PASSWORD = os.environ.get('AUTH_LDAP_BIND_PASSWORD', '')
# Set a string template that describes any users distinguished name based on the username.
AUTH_LDAP_USER_DN_TEMPLATE = os.environ.get('AUTH_LDAP_USER_DN_TEMPLATE', None)
# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert.
# Note that this is a NetBox-specific setting which sets:
# ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
LDAP_IGNORE_CERT_ERRORS = os.environ.get('LDAP_IGNORE_CERT_ERRORS', 'False').lower() == 'true'
AUTH_LDAP_USER_SEARCH = LDAPSearch(os.environ.get('AUTH_LDAP_USER_SEARCH_BASEDN', ''),
ldap.SCOPE_SUBTREE,
"(sAMAccountName=%(user)s)")
# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group
# heirarchy.
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(os.environ.get('AUTH_LDAP_GROUP_SEARCH_BASEDN', ''), ldap.SCOPE_SUBTREE,
"(objectClass=group)")
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
# Define a group required to login.
AUTH_LDAP_REQUIRE_GROUP = os.environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', '')
# Define special user types using groups. Exercise great caution when assigning superuser status.
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_active": os.environ.get('AUTH_LDAP_REQUIRE_GROUP_DN', ''),
"is_staff": os.environ.get('AUTH_LDAP_IS_ADMIN_DN', ''),
"is_superuser": os.environ.get('AUTH_LDAP_IS_SUPERUSER_DN', '')
}
# For more granular permissions, we can map LDAP groups to Django groups.
AUTH_LDAP_FIND_GROUP_PERMS = os.environ.get('AUTH_LDAP_FIND_GROUP_PERMS', 'True').lower() == 'true'
# Cache groups for one hour to reduce LDAP traffic
AUTH_LDAP_CACHE_GROUPS = os.environ.get('AUTH_LDAP_CACHE_GROUPS', 'True').lower() == 'true'
AUTH_LDAP_GROUP_CACHE_TIMEOUT = int(os.environ.get('AUTH_LDAP_GROUP_CACHE_TIMEOUT', 3600))
# Populate the Django user from the LDAP directory.
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": os.environ.get('AUTH_LDAP_ATTR_FIRSTNAME', 'givenName'),
"last_name": os.environ.get('AUTH_LDAP_ATTR_LASTNAME', 'sn'),
"email": os.environ.get('AUTH_LDAP_ATTR_MAIL', 'mail')
}

53
docker-compose.test.yml Normal file
View File

@ -0,0 +1,53 @@
version: '3.4'
services:
netbox:
image: ${IMAGE-netboxcommunity/netbox:latest}
depends_on:
- postgres
- redis
- redis-cache
env_file: env/netbox.env
user: '101'
volumes:
- ./startup_scripts:/opt/netbox/startup_scripts:z,ro
- ./${INITIALIZERS_DIR-initializers}:/opt/netbox/initializers:z,ro
- ./configuration:/etc/netbox/config:z,ro
- ./reports:/etc/netbox/reports:z,ro
- ./scripts:/etc/netbox/scripts:z,ro
- netbox-nginx-config:/etc/netbox-nginx:z
- netbox-static-files:/opt/netbox/netbox/static:z
- netbox-media-files:/opt/netbox/netbox/media:z
nginx:
command: nginx -c /etc/netbox-nginx/nginx.conf
image: nginx:1.19-alpine
depends_on:
- netbox
ports:
- 8080
volumes:
- netbox-static-files:/opt/netbox/netbox/static:ro
- netbox-nginx-config:/etc/netbox-nginx/:ro
postgres:
image: postgres:12-alpine
env_file: env/postgres.env
redis:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --appendonly yes --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis.env
redis-cache:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis-cache.env
volumes:
netbox-static-files:
driver: local
netbox-nginx-config:
driver: local
netbox-media-files:
driver: local

View File

@ -1,46 +1,78 @@
version: '3'
version: '3.4'
services:
netbox:
build:
context: .
args:
- BRANCH=${VERSION-master}
image: ninech/netbox:${VERSION-latest}
depends_on:
- postgres
env_file: netbox.env
volumes:
- ./startup_scripts:/opt/netbox/startup_scripts:ro
- ./initializers:/opt/netbox/initializers:ro
- ./configuration:/etc/netbox/config:ro
- netbox-nginx-config:/etc/netbox-nginx/
- netbox-static-files:/opt/netbox/netbox/static
- netbox-media-files:/opt/netbox/netbox/media
- netbox-report-files:/etc/netbox/reports:ro
nginx:
image: nginx:1.13-alpine
command: nginx -g 'daemon off;' -c /etc/netbox-nginx/nginx.conf
depends_on:
- netbox
ports:
- 8080
volumes:
- netbox-static-files:/opt/netbox/netbox/static:ro
- netbox-nginx-config:/etc/netbox-nginx/:ro
postgres:
image: postgres:10.4-alpine
env_file: postgres.env
volumes:
- netbox-postgres-data:/var/lib/postgresql/data
netbox: &netbox
image: netboxcommunity/netbox:${VERSION-latest}
depends_on:
- postgres
- redis
- redis-cache
- netbox-worker
env_file: env/netbox.env
user: '101'
volumes:
- ./startup_scripts:/opt/netbox/startup_scripts:z,ro
- ./initializers:/opt/netbox/initializers:z,ro
- ./configuration:/etc/netbox/config:z,ro
- ./reports:/etc/netbox/reports:z,ro
- ./scripts:/etc/netbox/scripts:z,ro
- netbox-nginx-config:/etc/netbox-nginx:z
- netbox-static-files:/opt/netbox/netbox/static:z
- netbox-media-files:/opt/netbox/netbox/media:z
netbox-worker:
<<: *netbox
depends_on:
- redis
entrypoint:
- python3
- /opt/netbox/netbox/manage.py
command:
- rqworker
# nginx
nginx:
command: nginx -c /etc/netbox-nginx/nginx.conf
image: nginx:1.19-alpine
depends_on:
- netbox
ports:
- 8080
volumes:
- netbox-static-files:/opt/netbox/netbox/static:ro
- netbox-nginx-config:/etc/netbox-nginx/:ro
# postgres
postgres:
image: postgres:12-alpine
env_file: env/postgres.env
volumes:
- netbox-postgres-data:/var/lib/postgresql/data
# redis
redis:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --appendonly yes --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis.env
volumes:
- netbox-redis-data:/data
redis-cache:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis-cache.env
volumes:
netbox-static-files:
driver: local
netbox-nginx-config:
driver: local
netbox-media-files:
driver: local
netbox-report-files:
driver: local
netbox-postgres-data:
driver: local
netbox-static-files:
driver: local
netbox-nginx-config:
driver: local
netbox-media-files:
driver: local
netbox-postgres-data:
driver: local
netbox-redis-data:
driver: local

View File

@ -1,10 +1,79 @@
## Generic Parts
# These functions are providing the functionality to load
# arbitrary configuration files.
#
# They can be imported by other code (see `ldap_config.py` for an example).
from os.path import abspath, isfile
from os import scandir
import importlib.util
import sys
try:
spec = importlib.util.spec_from_file_location('configuration', '/etc/netbox/config/configuration.py')
def _filename(f):
return f.name
def _import(module_name, path, loaded_configurations):
spec = importlib.util.spec_from_file_location('', path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules['netbox.configuration'] = module
except:
raise ImportError('')
sys.modules[module_name] = module
loaded_configurations.insert(0, module)
print(f"🧬 loaded config '{path}'")
def read_configurations(config_module, config_dir, main_config):
loaded_configurations = []
main_config_path = abspath(f'{config_dir}/{main_config}.py')
if isfile(main_config_path):
_import(f'{config_module}.{main_config}', main_config_path, loaded_configurations)
else:
print(f"⚠️ Main configuration '{main_config_path}' not found.")
with scandir(config_dir) as it:
for f in sorted(it, key=_filename):
if not f.is_file():
continue
if f.name.startswith('__'):
continue
if not f.name.endswith('.py'):
continue
if f.name == f'{config_dir}.py':
continue
module_name = f"{config_module}.{f.name[:-len('.py')]}".replace(".", "_")
_import(module_name, f.path, loaded_configurations)
if len(loaded_configurations) == 0:
print(f"‼️ No configuration files found in '{config_dir}'.")
raise ImportError(f"No configuration files found in '{config_dir}'.")
return loaded_configurations
## Specific Parts
# This section's code actually loads the various configuration files
# into the module with the given name.
# It contains the logic to resolve arbitrary configuration options by
# levaraging dynamic programming using `__getattr__`.
_loaded_configurations = read_configurations(
config_dir = '/etc/netbox/config/',
config_module = 'netbox.configuration',
main_config = 'configuration')
def __getattr__(name):
for config in _loaded_configurations:
try:
return getattr(config, name)
except:
pass
raise AttributeError

View File

@ -1,37 +1,48 @@
#!/bin/bash
# Runs on every start of the Netbox Docker container
# Stop when an error occures
set -e
# wait shortly and then run db migrations (retry on error)
while ! ./manage.py migrate 2>&1; do
echo "⏳ Waiting on DB..."
sleep 3
done
# Allows Netbox to be run as non-root users
umask 002
# create superuser silently
if [ -z ${SUPERUSER_NAME+x} ]; then
SUPERUSER_NAME='admin'
# Try to connect to the DB
DB_WAIT_TIMEOUT=${DB_WAIT_TIMEOUT-3}
MAX_DB_WAIT_TIME=${MAX_DB_WAIT_TIME-30}
CUR_DB_WAIT_TIME=0
while ! ./manage.py migrate 2>&1 && [ "${CUR_DB_WAIT_TIME}" -lt "${MAX_DB_WAIT_TIME}" ]; do
echo "⏳ Waiting on DB... (${CUR_DB_WAIT_TIME}s / ${MAX_DB_WAIT_TIME}s)"
sleep "${DB_WAIT_TIMEOUT}"
CUR_DB_WAIT_TIME=$(( CUR_DB_WAIT_TIME + DB_WAIT_TIMEOUT ))
done
if [ "${CUR_DB_WAIT_TIME}" -ge "${MAX_DB_WAIT_TIME}" ]; then
echo "❌ Waited ${MAX_DB_WAIT_TIME}s or more for the DB to become ready."
exit 1
fi
if [ -z ${SUPERUSER_EMAIL+x} ]; then
SUPERUSER_EMAIL='admin@example.com'
fi
if [ -z ${SUPERUSER_PASSWORD+x} ]; then
# Create Superuser if required
if [ "$SKIP_SUPERUSER" == "true" ]; then
echo "↩️ Skip creating the superuser"
else
if [ -z ${SUPERUSER_NAME+x} ]; then
SUPERUSER_NAME='admin'
fi
if [ -z ${SUPERUSER_EMAIL+x} ]; then
SUPERUSER_EMAIL='admin@example.com'
fi
if [ -f "/run/secrets/superuser_password" ]; then
SUPERUSER_PASSWORD="$(< /run/secrets/superuser_password)"
else
elif [ -z ${SUPERUSER_PASSWORD+x} ]; then
SUPERUSER_PASSWORD='admin'
fi
fi
if [ -z ${SUPERUSER_API_TOKEN+x} ]; then
if [ -f "/run/secrets/superuser_api_token" ]; then
SUPERUSER_API_TOKEN="$(< /run/secrets/superuser_api_token)"
else
elif [ -z ${SUPERUSER_API_TOKEN+x} ]; then
SUPERUSER_API_TOKEN='0123456789abcdef0123456789abcdef01234567'
fi
fi
echo "💡 Username: ${SUPERUSER_NAME}, E-Mail: ${SUPERUSER_EMAIL}"
./manage.py shell --interface python << END
./manage.py shell --interface python << END
from django.contrib.auth.models import User
from users.models import Token
if not User.objects.filter(username='${SUPERUSER_NAME}'):
@ -39,16 +50,23 @@ if not User.objects.filter(username='${SUPERUSER_NAME}'):
Token.objects.create(user=u, key='${SUPERUSER_API_TOKEN}')
END
for script in /opt/netbox/startup_scripts/*.py; do
echo "⚙️ Executing '$script'"
./manage.py shell --interface python < "${script}"
done
echo "💡 Superuser Username: ${SUPERUSER_NAME}, E-Mail: ${SUPERUSER_EMAIL}"
fi
# copy static files
# Run the startup scripts (and initializers)
if [ "$SKIP_STARTUP_SCRIPTS" == "true" ]; then
echo "↩️ Skipping startup scripts"
else
echo "import runpy; runpy.run_path('../startup_scripts')" | ./manage.py shell --interface python
fi
# Copy static files
./manage.py collectstatic --no-input
echo "✅ Initialisation is done."
# launch whatever is passed by docker
# Launch whatever is passed by docker
# (i.e. the RUN instruction in the Dockerfile)
exec ${@}
#
# shellcheck disable=SC2068
exec $@

View File

@ -5,4 +5,4 @@ workers = 3
errorlog = '-'
accesslog = '-'
capture_output = False
loglevel = 'debug'
loglevel = 'info'

View File

@ -1,10 +1,21 @@
import importlib.util
import sys
from .configuration import read_configurations
try:
spec = importlib.util.spec_from_file_location('ldap_config', '/etc/netbox/config/ldap_config.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules['netbox.ldap_config'] = module
except:
raise ImportError('')
_loaded_configurations = read_configurations(
config_dir = '/etc/netbox/config/ldap/',
config_module = 'netbox.configuration.ldap',
main_config = 'ldap_config')
def __getattr__(name):
for config in _loaded_configurations:
try:
return getattr(config, name)
except:
pass
raise AttributeError
def __dir__():
names = []
for config in _loaded_configurations:
names.extend(config.__dir__())
return names

View File

@ -1,5 +1,8 @@
daemon off;
worker_processes 1;
error_log /dev/stderr info;
events {
worker_connections 1024;
}
@ -16,7 +19,6 @@ http {
server {
listen 8080;
server_name localhost;
access_log off;
location /static/ {
@ -27,8 +29,16 @@ http {
proxy_pass http://netbox:8001;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
}
}
server {
listen 8081;
access_log off;
location = /stub_status {
stub_status;
}
}
}

39
env/netbox.env vendored Normal file
View File

@ -0,0 +1,39 @@
CORS_ORIGIN_ALLOW_ALL=True
DB_NAME=netbox
DB_USER=netbox
DB_PASSWORD=J5brHrAXFLQSif0K
DB_HOST=postgres
EMAIL_SERVER=localhost
EMAIL_PORT=25
EMAIL_USERNAME=netbox
EMAIL_PASSWORD=
EMAIL_TIMEOUT=5
EMAIL_FROM=netbox@bar.com
# 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
EMAIL_SSL_CERTFILE=
EMAIL_SSL_KEYFILE=
MAX_PAGE_SIZE=1000
MEDIA_ROOT=/opt/netbox/netbox/media
METRICS_ENABLED=false
NAPALM_USERNAME=
NAPALM_PASSWORD=
NAPALM_TIMEOUT=10
REDIS_HOST=redis
REDIS_PASSWORD=H733Kdjndks81
REDIS_DATABASE=0
REDIS_SSL=false
REDIS_CACHE_HOST=redis-cache
REDIS_CACHE_PASSWORD=t4Ph722qJ5QHeQ1qfu36
REDIS_CACHE_DATABASE=1
REDIS_CACHE_SSL=false
RELEASE_CHECK_URL=https://api.github.com/repos/netbox-community/netbox/releases
SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj
SKIP_STARTUP_SCRIPTS=false
SKIP_SUPERUSER=false
SUPERUSER_NAME=admin
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_PASSWORD=admin
SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567
WEBHOOKS_ENABLED=true

View File

1
env/redis-cache.env vendored Normal file
View File

@ -0,0 +1 @@
REDIS_PASSWORD=t4Ph722qJ5QHeQ1qfu36

1
env/redis.env vendored Normal file
View File

@ -0,0 +1 @@
REDIS_PASSWORD=H733Kdjndks81

View File

@ -0,0 +1,6 @@
# - prefix: 10.0.0.0/16
# rir: RFC1918
# - prefix: fd00:ccdd::/32
# rir: RFC4193 ULA
# - prefix: 2001:db8::/32
# rir: RFC3849

View File

@ -0,0 +1,2 @@
# - name: Hyper-V
# slug: hyper-v

View File

@ -0,0 +1,5 @@
# - name: cluster1
# type: Hyper-V
# - name: cluster2
# type: Hyper-V
# site: SING 1

View File

@ -1,3 +1,18 @@
## Possible Choices:
## type:
## - text
## - integer
## - boolean
## - date
## - url
## - select
## filter_logic:
## - disabled
## - loose
## - exact
##
## Examples:
# text_field:
# type: text
# label: Custom Text
@ -7,6 +22,8 @@
# on_objects:
# - dcim.models.Device
# - dcim.models.Rack
# - dcim.models.Site
# - dcim.models.DeviceType
# - ipam.models.IPAddress
# - ipam.models.Prefix
# - tenancy.models.Tenant
@ -20,8 +37,8 @@
# weight: 10
# on_objects:
# - tenancy.models.Tenant
# selection_field:
# type: selection
# select_field:
# type: select
# label: Choose between items
# required: false
# filter_logic: exact
@ -39,8 +56,8 @@
# weight: 50
# - value: Fourth Item
# weight: 40
# selection_field_auto_weight:
# type: selection
# select_field_auto_weight:
# type: select
# label: Choose between items
# required: false
# filter_logic: loose

View File

@ -0,0 +1,18 @@
## Possible Choices:
## type:
## - virtual
## - lag
## - 1000base-t
## - ... and many more. See for yourself:
## https://github.com/netbox-community/netbox/blob/295d4f0394b431351c0cb2c3ecc791df68c6c2fb/netbox/dcim/choices.py#L510
##
## Examples:
# - device: server01
# enabled: true
# type: virtual
# name: to-server02
# - device: server02
# enabled: true
# type: virtual
# name: to-server01

View File

@ -0,0 +1,15 @@
# - name: switch
# slug: switch
# color: Grey
# - name: router
# slug: router
# color: Cyan
# - name: load-balancer
# slug: load-balancer
# color: Red
# - name: server
# slug: server
# color: Blue
# - name: patchpanel
# slug: patchpanel
# color: Black

View File

@ -0,0 +1,23 @@
# - model: Model 1
# manufacturer: Manufacturer 1
# slug: model-1
# u_height: 2
# custom_fields:
# text_field: Description
# - model: Model 2
# manufacturer: Manufacturer 1
# slug: model-2
# custom_fields:
# text_field: Description
# - model: Model 3
# manufacturer: Manufacturer 1
# slug: model-3
# is_full_depth: false
# u_height: 0
# custom_fields:
# text_field: Description
# - model: Other
# manufacturer: No Name
# slug: other
# custom_fields:
# text_field: Description

44
initializers/devices.yml Normal file
View File

@ -0,0 +1,44 @@
## Possible Choices:
## face:
## - front
## - rear
## status:
## - offline
## - active
## - planned
## - staged
## - failed
## - inventory
## - decommissioning
##
## Examples:
# - name: server01
# device_role: server
# device_type: Other
# site: AMS 1
# rack: rack-01
# face: front
# position: 1
# custom_fields:
# text_field: Description
# - name: server02
# device_role: server
# device_type: Other
# site: AMS 2
# rack: rack-02
# face: front
# position: 2
# primary_ip4: 10.1.1.2/24
# primary_ip6: 2001:db8:a000:1::2/64
# custom_fields:
# text_field: Description
# - name: server03
# device_role: server
# device_type: Other
# site: SING 1
# rack: rack-03
# face: front
# position: 3
# custom_fields:
# text_field: Description

View File

@ -1,3 +1,15 @@
## 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:
# users:
# - technical_user
@ -7,3 +19,17 @@
# writers:
# users:
# - writer
# permissions:
# - delete_device
# - delete_virtualmachine
# - add_*
# - change_*
# vm_managers:
# permissions:
# - '*_virtualmachine'
# device_managers:
# permissions:
# - '*device*'
# creators:
# permissions:
# - add_*

View File

@ -0,0 +1,44 @@
## Possible Choices:
## status:
## - active
## - reserved
## - deprecated
## - dhcp
## role:
## - loopback
## - secondary
## - anycast
## - vip
## - vrrp
## - hsrp
## - glbp
## - carp
##
## Examples:
# - address: 10.1.1.1/24
# device: server01
# interface: to-server02
# status: active
# vrf: vrf1
# - address: 2001:db8:a000:1::1/64
# device: server01
# interface: to-server02
# status: active
# vrf: vrf1
# - address: 10.1.1.2/24
# device: server02
# interface: to-server01
# status: active
# - address: 2001:db8:a000:1::2/64
# device: server02
# interface: to-server01
# status: active
# - address: 10.1.1.10/24
# description: reserved IP
# status: reserved
# tenant: tenant1
# - address: 2001:db8:a000:1::10/64
# description: reserved IP
# status: reserved
# tenant: tenant1

View File

@ -0,0 +1,6 @@
# - name: Manufacturer 1
# slug: manufacturer-1
# - name: Manufacturer 2
# slug: manufacturer-2
# - name: No Name
# slug: no-name

View File

@ -0,0 +1,15 @@
# - name: Platform 1
# slug: platform-1
# manufacturer: Manufacturer 1
# napalm_driver: driver1
# napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}"
# - name: Platform 2
# slug: platform-2
# manufacturer: Manufacturer 2
# napalm_driver: driver2
# napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}"
# - name: Platform 3
# slug: platform-3
# manufacturer: No Name
# napalm_driver: driver3
# napalm_args: "{'arg1': 'value1', 'arg2': 'value2'}"

View File

@ -0,0 +1,2 @@
# - name: Main Management
# slug: main-management

29
initializers/prefixes.yml Normal file
View File

@ -0,0 +1,29 @@
## Possible Choices:
## status:
## - container
## - active
## - reserved
## - deprecated
##
## Examples:
# - description: prefix1
# prefix: 10.1.1.0/24
# site: AMS 1
# status: active
# tenant: tenant1
# vlan: vlan1
# - description: prefix2
# prefix: 10.1.2.0/24
# site: AMS 2
# status: active
# tenant: tenant2
# vlan: vlan2
# is_pool: true
# vrf: vrf2
# - description: ipv6 prefix1
# prefix: 2001:db8:a000:1::/64
# site: AMS 2
# status: active
# tenant: tenant2
# vlan: vlan2

View File

@ -0,0 +1,3 @@
# - name: cage 101
# slug: cage-101
# site: SING 1

View File

@ -0,0 +1,12 @@
# - name: Role 1
# slug: role-1
# color: Pink
# - name: Role 2
# slug: role-2
# color: Cyan
# - name: Role 3
# slug: role-3
# color: Grey
# - name: Role 4
# slug: role-4
# color: Teal

41
initializers/racks.yml Normal file
View File

@ -0,0 +1,41 @@
## Possible Choices:
## width:
## - 19
## - 23
## types:
## - 2-post-frame
## - 4-post-frame
## - 4-post-cabinet
## - wall-frame
## - wall-cabinet
## outer_unit:
## - mm
## - in
##
## Examples:
# - site: AMS 1
# name: rack-01
# role: Role 1
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# text_field: Description
# - site: AMS 2
# name: rack-02
# role: Role 2
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# text_field: Description
# - site: SING 1
# name: rack-03
# group: cage 101
# role: Role 3
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# text_field: Description

10
initializers/regions.yml Normal file
View File

@ -0,0 +1,10 @@
# - name: Singapore
# slug: singapore
# - name: Amsterdam
# slug: amsterdam
# - name: Downtown
# slug: downtown
# parent: Amsterdam
# - name: Suburbs
# slug: suburbs
# parent: Amsterdam

9
initializers/rirs.yml Normal file
View File

@ -0,0 +1,9 @@
# - is_private: true
# name: RFC1918
# slug: rfc1918
# - is_private: true
# name: RFC4193 ULA
# slug: rfc4193-ula
# - is_private: true
# name: RFC3849
# slug: rfc3849

32
initializers/sites.yml Normal file
View File

@ -0,0 +1,32 @@
# - name: AMS 1
# slug: ams1
# region: Downtown
# status: active
# facility: Amsterdam 1
# asn: 12345
# custom_fields:
# text_field: Description
# - name: AMS 2
# slug: ams2
# region: Downtown
# status: active
# facility: Amsterdam 2
# asn: 54321
# custom_fields:
# text_field: Description
# - name: AMS 3
# slug: ams3
# region: Suburbs
# status: active
# facility: Amsterdam 3
# asn: 67890
# custom_fields:
# text_field: Description
# - name: SING 1
# slug: sing1
# region: Singapore
# status: active
# facility: Singapore 1
# asn: 09876
# custom_fields:
# text_field: Description

View File

@ -0,0 +1,4 @@
# - name: Tenant Group 1
# slug: tenant-group-1
# - name: Tenant Group 2
# slug: tenant-group-2

5
initializers/tenants.yml Normal file
View File

@ -0,0 +1,5 @@
# - name: tenant1
# slug: tenant1
# - name: tenant2
# slug: tenant2
# group: Tenant Group 2

View File

@ -1,6 +1,23 @@
## 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_*

View File

@ -0,0 +1,28 @@
## Possible Choices:
## status:
## - active
## - offline
## - staged
##
## Examples:
# - cluster: cluster1
# comments: VM1
# disk: 200
# memory: 4096
# name: virtual machine 1
# platform: Platform 2
# status: active
# tenant: tenant1
# vcpus: 8
# - cluster: cluster1
# comments: VM2
# disk: 100
# memory: 2048
# name: virtual machine 2
# platform: Platform 2
# primary_ip4: 10.1.1.10/24
# primary_ip6: 2001:db8:a000:1::10/64
# status: active
# tenant: tenant1
# vcpus: 8

View File

@ -0,0 +1,12 @@
# - description: Network Interface 1
# enabled: true
# mac_address: 00:77:77:77:77:77
# mtu: 1500
# name: Network Interface 1
# virtual_machine: virtual machine 1
# - description: Network Interface 2
# enabled: true
# mac_address: 00:55:55:55:55:55
# mtu: 1500
# name: Network Interface 2
# virtual_machine: virtual machine 1

View File

@ -0,0 +1,6 @@
# - name: VLAN group 1
# site: AMS 1
# slug: vlan-group-1
# - name: VLAN group 2
# site: AMS 1
# slug: vlan-group-2

19
initializers/vlans.yml Normal file
View File

@ -0,0 +1,19 @@
## Possible Choices:
## status:
## - active
## - reserved
## - deprecated
##
## Examples:
# - name: vlan1
# site: AMS 1
# status: active
# vid: 5
# role: Main Management
# description: VLAN 5 for MGMT
# - group: VLAN group 2
# name: vlan2
# site: AMS 1
# status: active
# vid: 1300

8
initializers/vrfs.yml Normal file
View File

@ -0,0 +1,8 @@
# - enforce_unique: true
# name: vrf1
# tenant: tenant1
# description: main VRF
# - enforce_unique: true
# name: vrf2
# rd: "6500:6500"
# tenant: tenant2

View File

@ -1,20 +0,0 @@
DB_NAME=netbox
DB_USER=netbox
DB_PASSWORD=J5brHrAXFLQSif0K
DB_HOST=postgres
EMAIL_SERVER=localhost
EMAIL_PORT=25
EMAIL_USERNAME=netbox
EMAIL_PASSWORD=
EMAIL_TIMEOUT=5
EMAIL_FROM=netbox@bar.com
MEDIA_ROOT=/opt/netbox/netbox/media
NAPALM_USERNAME=
NAPALM_PASSWORD=
NAPALM_TIMEOUT=10
MAX_PAGE_SIZE=0
SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj
SUPERUSER_NAME=admin
SUPERUSER_EMAIL=admin@example.com
SUPERUSER_PASSWORD=admin
SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567

View File

@ -0,0 +1,46 @@
from dcim.choices import DeviceStatusChoices
from dcim.models import ConsolePort, Device, PowerPort
from extras.reports import Report
class DeviceConnectionsReport(Report):
description = "Validate the minimum physical connections for each device"
def test_console_connection(self):
# Check that every console port for every active device has a connection defined.
active = DeviceStatusChoices.STATUS_ACTIVE
for console_port in ConsolePort.objects.prefetch_related('device').filter(device__status=active):
if console_port.connected_endpoint is None:
self.log_failure(
console_port.device,
"No console connection defined for {}".format(console_port.name)
)
elif not console_port.connection_status:
self.log_warning(
console_port.device,
"Console connection for {} marked as planned".format(console_port.name)
)
else:
self.log_success(console_port.device)
def test_power_connections(self):
# Check that every active device has at least two connected power supplies.
for device in Device.objects.filter(status=DeviceStatusChoices.STATUS_ACTIVE):
connected_ports = 0
for power_port in PowerPort.objects.filter(device=device):
if power_port.connected_endpoint is not None:
connected_ports += 1
if not power_port.connection_status:
self.log_warning(
device,
"Power connection for {} marked as planned".format(power_port.name)
)
if connected_ports < 2:
self.log_failure(
device,
"{} connected power supplies found (2 needed)".format(connected_ports)
)
else:
self.log_success(device)

0
scripts/__init__.py Normal file
View File

View File

@ -0,0 +1,23 @@
import sys
from django.contrib.auth.models import Group, User
from startup_script_utils import load_yaml, set_permissions
from users.models import Token
users = load_yaml('/opt/netbox/initializers/users.yml')
if users is None:
sys.exit()
for username, user_details in users.items():
if not User.objects.filter(username=username):
user = User.objects.create_user(
username = username,
password = user_details.get('password', 0) or User.objects.make_random_password())
print("👤 Created user",username)
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)

View File

@ -1,20 +0,0 @@
from django.contrib.auth.models import Group, User
from users.models import Token
from ruamel.yaml import YAML
with open('/opt/netbox/initializers/users.yml', 'r') as stream:
yaml=YAML(typ='safe')
users = yaml.load(stream)
if users is not None:
for username, user_details in users.items():
if not User.objects.filter(username=username):
user = User.objects.create_user(
username = username,
password = user_details.get('password', 0) or User.objects.make_random_password)
print("👤 Created user ",username)
if user_details.get('api_token', 0):
Token.objects.create(user=user, key=user_details['api_token'])

View File

@ -0,0 +1,23 @@
import sys
from django.contrib.auth.models import Group, User
from startup_script_utils import load_yaml, set_permissions
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)
if created:
print("👥 Created group", groupname)
for username in group_details.get('users', []):
user = User.objects.get(username=username)
if user:
user.groups.add(group)
yaml_permissions = group_details.get('permissions', [])
set_permissions(group.permissions, yaml_permissions)

View File

@ -0,0 +1,54 @@
from extras.models import CustomField, CustomFieldChoice
from startup_script_utils import load_yaml
import sys
def get_class_for_class_path(class_path):
import importlib
from django.contrib.contenttypes.models import ContentType
module_name, class_name = class_path.rsplit(".", 1)
module = importlib.import_module(module_name)
clazz = getattr(module, class_name)
return ContentType.objects.get_for_model(clazz)
customfields = load_yaml('/opt/netbox/initializers/custom_fields.yml')
if customfields is None:
sys.exit()
for cf_name, cf_details in customfields.items():
custom_field, created = CustomField.objects.get_or_create(name = cf_name)
if created:
if cf_details.get('default', 0):
custom_field.default = cf_details['default']
if cf_details.get('description', 0):
custom_field.description = cf_details['description']
if cf_details.get('label', 0):
custom_field.label = cf_details['label']
for object_type in cf_details.get('on_objects', []):
custom_field.obj_type.add(get_class_for_class_path(object_type))
if cf_details.get('required', 0):
custom_field.required = cf_details['required']
if cf_details.get('type', 0):
custom_field.type = cf_details['type']
if cf_details.get('weight', 0):
custom_field.weight = cf_details['weight']
custom_field.save()
for idx, choice_details in enumerate(cf_details.get('choices', [])):
choice, _ = CustomFieldChoice.objects.get_or_create(
field=custom_field,
value=choice_details['value'],
defaults={'weight': idx * 10}
)
print("🔧 Created custom field", cf_name)

View File

@ -0,0 +1,26 @@
from dcim.models import Region
from startup_script_utils import load_yaml
import sys
regions = load_yaml('/opt/netbox/initializers/regions.yml')
if regions is None:
sys.exit()
optional_assocs = {
'parent': (Region, 'name')
}
for params in regions:
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)
region, created = Region.objects.get_or_create(**params)
if created:
print("🌐 Created region", region.name)

View File

@ -0,0 +1,41 @@
from dcim.models import Region, Site
from extras.models import CustomField, CustomFieldValue
from tenancy.models import Tenant
from startup_script_utils import load_yaml
import sys
sites = load_yaml('/opt/netbox/initializers/sites.yml')
if sites is None:
sys.exit()
optional_assocs = {
'region': (Region, 'name'),
'tenant': (Tenant, 'name')
}
for params in sites:
custom_fields = params.pop('custom_fields', None)
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)
site, created = Site.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=site,
value=cf_value
)
site.custom_field_values.add(custom_field_value)
print("📍 Created site", site.name)

View File

@ -0,0 +1,14 @@
from dcim.models import Manufacturer
from startup_script_utils import load_yaml
import sys
manufacturers = load_yaml('/opt/netbox/initializers/manufacturers.yml')
if manufacturers is None:
sys.exit()
for params in manufacturers:
manufacturer, created = Manufacturer.objects.get_or_create(**params)
if created:
print("🏭 Created Manufacturer", manufacturer.name)

View File

@ -0,0 +1,51 @@
from dcim.models import DeviceType, Manufacturer, Region
from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
device_types = load_yaml('/opt/netbox/initializers/device_types.yml')
if device_types is None:
sys.exit()
required_assocs = {
'manufacturer': (Manufacturer, 'name')
}
optional_assocs = {
'region': (Region, 'name'),
'tenant': (Tenant, 'name')
}
for params in device_types:
custom_fields = params.pop('custom_fields', 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_type, created = DeviceType.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device_type,
value=cf_value
)
device_type.custom_field_values.add(custom_field_value)
print("🔡 Created device type", device_type.manufacturer, device_type.model)

View File

@ -0,0 +1,23 @@
from dcim.models import RackRole
from utilities.choices import ColorChoices
from startup_script_utils import load_yaml
import sys
rack_roles = load_yaml('/opt/netbox/initializers/rack_roles.yml')
if rack_roles is None:
sys.exit()
for params in rack_roles:
if 'color' in params:
color = params.pop('color')
for color_tpl in ColorChoices:
if color in color_tpl:
params['color'] = color_tpl[0]
rack_role, created = RackRole.objects.get_or_create(**params)
if created:
print("🎨 Created rack role", rack_role.name)

View File

@ -0,0 +1,25 @@
from dcim.models import Site,RackGroup
from startup_script_utils import load_yaml
import sys
rack_groups = load_yaml('/opt/netbox/initializers/rack_groups.yml')
if rack_groups is None:
sys.exit()
required_assocs = {
'site': (Site, 'name')
}
for params in rack_groups:
for assoc, details in required_assocs.items():
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
rack_group, created = RackGroup.objects.get_or_create(**params)
if created:
print("🎨 Created rack group", rack_group.name)

View File

@ -0,0 +1,52 @@
from dcim.models import Site, RackRole, Rack, RackGroup
from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
racks = load_yaml('/opt/netbox/initializers/racks.yml')
if racks is None:
sys.exit()
required_assocs = {
'site': (Site, 'name')
}
optional_assocs = {
'role': (RackRole, 'name'),
'tenant': (Tenant, 'name'),
'group': (RackGroup, 'name')
}
for params in racks:
custom_fields = params.pop('custom_fields', 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)
rack, created = Rack.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=rack,
value=cf_value
)
rack.custom_field_values.add(custom_field_value)
print("🔳 Created rack", rack.site, rack.name)

View File

@ -0,0 +1,24 @@
from dcim.models import DeviceRole
from utilities.choices import ColorChoices
from startup_script_utils import load_yaml
import sys
device_roles = load_yaml('/opt/netbox/initializers/device_roles.yml')
if device_roles is None:
sys.exit()
for params in device_roles:
if 'color' in params:
color = params.pop('color')
for color_tpl in ColorChoices:
if color in color_tpl:
params['color'] = color_tpl[0]
device_role, created = DeviceRole.objects.get_or_create(**params)
if created:
print("🎨 Created device role", device_role.name)

View File

@ -0,0 +1,26 @@
from dcim.models import Manufacturer, Platform
from startup_script_utils import load_yaml
import sys
platforms = load_yaml('/opt/netbox/initializers/platforms.yml')
if platforms is None:
sys.exit()
optional_assocs = {
'manufacturer': (Manufacturer, 'name'),
}
for params in platforms:
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)
platform, created = Platform.objects.get_or_create(**params)
if created:
print("💾 Created platform", platform.name)

View File

@ -1,19 +0,0 @@
from django.contrib.auth.models import Group, User
from ruamel.yaml import YAML
with open('/opt/netbox/initializers/groups.yml', 'r') as stream:
yaml=YAML(typ='safe')
groups = yaml.load(stream)
if groups is not None:
for groupname, group_details in groups.items():
group, created = Group.objects.get_or_create(name=groupname)
if created:
print("👥 Created group", groupname)
for username in group_details['users']:
user = User.objects.get(username=username)
if user:
user.groups.add(group)

View File

@ -0,0 +1,14 @@
from tenancy.models import TenantGroup
from startup_script_utils import load_yaml
import sys
tenant_groups = load_yaml('/opt/netbox/initializers/tenant_groups.yml')
if tenant_groups is None:
sys.exit()
for params in tenant_groups:
tenant_group, created = TenantGroup.objects.get_or_create(**params)
if created:
print("🔳 Created Tenant Group", tenant_group.name)

View File

@ -0,0 +1,39 @@
from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
tenants = load_yaml('/opt/netbox/initializers/tenants.yml')
if tenants is None:
sys.exit()
optional_assocs = {
'group': (TenantGroup, 'name')
}
for params in tenants:
custom_fields = params.pop('custom_fields', None)
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)
tenant, created = Tenant.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=tenant,
value=cf_value
)
tenant.custom_field_values.add(custom_field_value)
print("👩‍💻 Created Tenant", tenant.name)

View File

@ -0,0 +1,59 @@
from dcim.models import Site, Rack, DeviceRole, DeviceType, Device, Platform
from virtualization.models import Cluster
from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
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_fields = params.pop('custom_fields', None)
# 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:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device,
value=cf_value
)
device.custom_field_values.add(custom_field_value)
print("🖥️ Created device", device.name)

View File

@ -0,0 +1,14 @@
from virtualization.models import ClusterType
from startup_script_utils import load_yaml
import sys
cluster_types = load_yaml('/opt/netbox/initializers/cluster_types.yml')
if cluster_types is None:
sys.exit()
for params in cluster_types:
cluster_type, created = ClusterType.objects.get_or_create(**params)
if created:
print("🧰 Created Cluster Type", cluster_type.name)

View File

@ -0,0 +1,14 @@
from ipam.models import RIR
from startup_script_utils import load_yaml
import sys
rirs = load_yaml('/opt/netbox/initializers/rirs.yml')
if rirs is None:
sys.exit()
for params in rirs:
rir, created = RIR.objects.get_or_create(**params)
if created:
print("🗺️ Created RIR", rir.name)

View File

@ -0,0 +1,42 @@
from ipam.models import Aggregate, RIR
from extras.models import CustomField, CustomFieldValue
from netaddr import IPNetwork
from startup_script_utils import load_yaml
import sys
aggregates = load_yaml('/opt/netbox/initializers/aggregates.yml')
if aggregates is None:
sys.exit()
required_assocs = {
'rir': (RIR, 'name')
}
for params in aggregates:
custom_fields = params.pop('custom_fields', None)
params['prefix'] = IPNetwork(params['prefix'])
for assoc, details in required_assocs.items():
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
aggregate, created = Aggregate.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=aggregate,
value=cf_value
)
aggregate.custom_field_values.add(custom_field_value)
print("🗞️ Created Aggregate", aggregate.prefix)

View File

@ -0,0 +1,51 @@
from dcim.models import Site
from virtualization.models import Cluster, ClusterType, ClusterGroup
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
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')
}
for params in clusters:
custom_fields = params.pop('custom_fields', 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)
cluster, created = Cluster.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=cluster,
value=cf_value
)
cluster.custom_field_values.add(custom_field_value)
print("🗄️ Created cluster", cluster.name)

View File

@ -0,0 +1,42 @@
from ipam.models import VRF
from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
vrfs = load_yaml('/opt/netbox/initializers/vrfs.yml')
if vrfs is None:
sys.exit()
optional_assocs = {
'tenant': (Tenant, 'name')
}
for params in vrfs:
custom_fields = params.pop('custom_fields', None)
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)
vrf, created = VRF.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vrf,
value=cf_value
)
vrf.custom_field_values.add(custom_field_value)
print("📦 Created VRF", vrf.name)

View File

@ -0,0 +1,14 @@
from ipam.models import Role
from startup_script_utils import load_yaml
import sys
roles = load_yaml('/opt/netbox/initializers/prefix_vlan_roles.yml')
if roles is None:
sys.exit()
for params in roles:
role, created = Role.objects.get_or_create(**params)
if created:
print("⛹️‍ Created Prefix/VLAN Role", role.name)

View File

@ -0,0 +1,40 @@
from dcim.models import Site
from ipam.models import VLANGroup
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
vlan_groups = load_yaml('/opt/netbox/initializers/vlan_groups.yml')
if vlan_groups is None:
sys.exit()
optional_assocs = {
'site': (Site, 'name')
}
for params in vlan_groups:
custom_fields = params.pop('custom_fields', None)
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)
vlan_group, created = VLANGroup.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan_group,
value=cf_value
)
vlan_group.custom_field_values.add(custom_field_value)
print("🏘️ Created VLAN Group", vlan_group.name)

View File

@ -1,69 +0,0 @@
from extras.constants import CF_TYPE_TEXT, CF_TYPE_INTEGER, CF_TYPE_BOOLEAN, CF_TYPE_DATE, CF_TYPE_URL, CF_TYPE_SELECT, CF_FILTER_CHOICES
from extras.models import CustomField, CustomFieldChoice
from ruamel.yaml import YAML
text_to_fields = {
'boolean': CF_TYPE_BOOLEAN,
'date': CF_TYPE_DATE,
'integer': CF_TYPE_INTEGER,
'selection': CF_TYPE_SELECT,
'text': CF_TYPE_TEXT,
'url': CF_TYPE_URL,
}
def get_class_for_class_path(class_path):
import importlib
from django.contrib.contenttypes.models import ContentType
module_name, class_name = class_path.rsplit(".", 1)
module = importlib.import_module(module_name)
clazz = getattr(module, class_name)
return ContentType.objects.get_for_model(clazz)
with open('/opt/netbox/initializers/custom_fields.yml', 'r') as stream:
yaml = YAML(typ='safe')
customfields = yaml.load(stream)
if customfields is not None:
for cf_name, cf_details in customfields.items():
custom_field, created = CustomField.objects.get_or_create(name = cf_name)
if created:
if cf_details.get('default', 0):
custom_field.default = cf_details['default']
if cf_details.get('description', 0):
custom_field.description = cf_details['description']
# If no filter_logic is specified then it will default to 'Loose'
if cf_details.get('filter_logic', 0):
for choice_id, choice_text in CF_FILTER_CHOICES:
if choice_text.lower() == cf_details['filter_logic']:
custom_field.filter_logic = choice_id
if cf_details.get('label', 0):
custom_field.label = cf_details['label']
for object_type in cf_details.get('on_objects', []):
custom_field.obj_type.add(get_class_for_class_path(object_type))
if cf_details.get('required', 0):
custom_field.required = cf_details['required']
if cf_details.get('type', 0):
custom_field.type = text_to_fields[cf_details['type']]
if cf_details.get('weight', 0):
custom_field.weight = cf_details['weight']
custom_field.save()
for idx, choice_details in enumerate(cf_details.get('choices', [])):
choice, _ = CustomFieldChoice.objects.get_or_create(
field=custom_field,
value=choice_details['value'],
defaults={'weight': idx * 10}
)
print("🔧 Created custom field", cf_name)

View File

@ -0,0 +1,45 @@
from dcim.models import Site
from ipam.models import VLAN, VLANGroup, Role
from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
vlans = load_yaml('/opt/netbox/initializers/vlans.yml')
if vlans is None:
sys.exit()
optional_assocs = {
'site': (Site, 'name'),
'tenant': (Tenant, 'name'),
'tenant_group': (TenantGroup, 'name'),
'group': (VLANGroup, 'name'),
'role': (Role, 'name')
}
for params in vlans:
custom_fields = params.pop('custom_fields', None)
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)
vlan, created = VLAN.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan,
value=cf_value
)
vlan.custom_field_values.add(custom_field_value)
print("🏠 Created VLAN", vlan.name)

View File

@ -0,0 +1,46 @@
from dcim.models import Site
from ipam.models import Prefix, VLAN, Role, VRF
from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue
from netaddr import IPNetwork
from startup_script_utils import load_yaml
import sys
prefixes = load_yaml('/opt/netbox/initializers/prefixes.yml')
if prefixes is None:
sys.exit()
optional_assocs = {
'site': (Site, 'name'),
'tenant': (Tenant, 'name'),
'tenant_group': (TenantGroup, 'name'),
'vlan': (VLAN, 'name'),
'role': (Role, 'name'),
'vrf': (VRF, 'name')
}
for params in prefixes:
custom_fields = params.pop('custom_fields', None)
params['prefix'] = IPNetwork(params['prefix'])
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)
prefix, created = Prefix.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=prefix,
value=cf_value
)
prefix.custom_field_values.add(custom_field_value)
print("📌 Created Prefix", prefix.prefix)

View File

@ -0,0 +1,56 @@
from dcim.models import Site, Platform, DeviceRole
from virtualization.models import Cluster, VirtualMachine
from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
virtual_machines = load_yaml('/opt/netbox/initializers/virtual_machines.yml')
if virtual_machines is None:
sys.exit()
required_assocs = {
'cluster': (Cluster, 'name')
}
optional_assocs = {
'tenant': (Tenant, 'name'),
'platform': (Platform, 'name'),
'role': (DeviceRole, 'name')
}
for params in virtual_machines:
custom_fields = params.pop('custom_fields', None)
# 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)
virtual_machine, created = VirtualMachine.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=virtual_machine,
value=cf_value
)
virtual_machine.custom_field_values.add(custom_field_value)
print("🖥️ Created virtual machine", virtual_machine.name)

View File

@ -0,0 +1,38 @@
from virtualization.models import VirtualMachine, VMInterface
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
interfaces = load_yaml('/opt/netbox/initializers/virtualization_interfaces.yml')
if interfaces is None:
sys.exit()
required_assocs = {
'virtual_machine': (VirtualMachine, 'name')
}
for params in interfaces:
custom_fields = params.pop('custom_fields', None)
for assoc, details in required_assocs.items():
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
interface, created = VMInterface.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
interface.custom_field_values.add(custom_field_value)
print("🧷 Created interface", interface.name, interface.virtual_machine.name)

View File

@ -0,0 +1,38 @@
from dcim.models import Interface, Device
from extras.models import CustomField, CustomFieldValue
from startup_script_utils import load_yaml
import sys
interfaces= load_yaml('/opt/netbox/initializers/dcim_interfaces.yml')
if interfaces is None:
sys.exit()
required_assocs = {
'device': (Device, 'name')
}
for params in interfaces:
custom_fields = params.pop('custom_fields', None)
for assoc, details in required_assocs.items():
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
interface, created = Interface.objects.get_or_create(**params)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
interface.custom_field_values.add(custom_field_value)
print("🧷 Created interface", interface.name, interface.device.name)

View File

@ -0,0 +1,69 @@
import sys
from dcim.models import Device, Interface
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from extras.models import CustomField, CustomFieldValue
from ipam.models import VRF, IPAddress
from netaddr import IPNetwork
from startup_script_utils import load_yaml
from tenancy.models import Tenant
from virtualization.models import VirtualMachine, VMInterface
ip_addresses = load_yaml('/opt/netbox/initializers/ip_addresses.yml')
if ip_addresses is None:
sys.exit()
optional_assocs = {
'tenant': (Tenant, 'name'),
'vrf': (VRF, 'name'),
'interface': (None, None)
}
vm_interface_ct = ContentType.objects.filter(Q(app_label='virtualization', model='vminterface')).first()
interface_ct = ContentType.objects.filter(Q(app_label='dcim', model='interface')).first()
for params in ip_addresses:
vm = params.pop('virtual_machine', None)
device = params.pop('device', None)
custom_fields = params.pop('custom_fields', None)
params['address'] = IPNetwork(params['address'])
if vm and device:
print("IP Address can only specify one of the following: virtual_machine or device.")
sys.exit()
for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
if assoc == 'interface':
if vm:
vm_id = VirtualMachine.objects.get(name=vm).id
query = { 'name': params.pop(assoc), "virtual_machine_id": vm_id }
params['assigned_object_type'] = vm_interface_ct
params['assigned_object_id'] = VMInterface.objects.get(**query).id
elif device:
dev_id = Device.objects.get(name=device).id
query = { 'name': params.pop(assoc), "device_id": dev_id }
params['assigned_object_type'] = interface_ct
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)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=ip_address,
value=cf_value
)
ip_address.custom_field_values.add(custom_field_value)
print("🧬 Created IP Address", ip_address.address)

View File

@ -0,0 +1,43 @@
from dcim.models import Device
from ipam.models import IPAddress
from virtualization.models import VirtualMachine
from startup_script_utils import load_yaml
import sys
def link_primary_ip(assets, asset_model):
for params in assets:
primary_ip_fields = set(params) & {'primary_ip4', 'primary_ip6'}
if not primary_ip_fields:
continue
for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
try:
params[assoc] = model.objects.get(**query)
except model.DoesNotExist:
primary_ip_fields -= {assoc}
print(f"⚠️ IP Address '{query[field]}' not found")
asset = asset_model.objects.get(name=params['name'])
for field in primary_ip_fields:
if getattr(asset, field) != params[field]:
setattr(asset, field, params[field])
print(f"🔗 Define primary IP '{params[field].address}' on '{asset.name}'")
asset.save()
devices = load_yaml('/opt/netbox/initializers/devices.yml')
virtual_machines = load_yaml('/opt/netbox/initializers/virtual_machines.yml')
if devices is None and virtual_machines is None:
sys.exit()
optional_assocs = {
'primary_ip4': (IPAddress, 'address'),
'primary_ip6': (IPAddress, 'address')
}
link_primary_ip(devices, Device)
link_primary_ip(virtual_machines, VirtualMachine)

Some files were not shown because too many files have changed in this diff Show More