Skip to content

Commit

Permalink
Merge pull request #371 from netbox-community/develop
Browse files Browse the repository at this point in the history
Version 0.27.0
  • Loading branch information
cimnine authored Dec 15, 2020
2 parents a51ad36 + 4e8588a commit aa4d630
Show file tree
Hide file tree
Showing 33 changed files with 224 additions and 288 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ jobs:
- ./build.sh develop
docker_from:
- '' # use the default of the build script
- python:3.8-alpine
- python:3.9-alpine
# - python:3.10-rc-alpine # disable until dependencies work
fail-fast: false
runs-on: ubuntu-latest
name: Builds new Netbox Docker Images
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,34 @@ jobs:
name: Logout of the Docker Registry
run: docker logout "${DOCKER_REGISTRY}"
if: steps.docker-build.outputs.skipped != 'true'

# Quay.io
- id: quayio-docker-build
name: Build the image with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }}
env:
DOCKER_REGISTRY: quay.io
GH_ACTION: enable
- id: quayio-registry-login
name: Login to the Quay.io Registry
run: |
echo "::add-mask::$QUAYIO_USERNAME"
echo "::add-mask::$QUAYIO_PASSWORD"
docker login -u "$QUAYIO_USERNAME" --password "${QUAYIO_PASSWORD}" "${DOCKER_REGISTRY}"
env:
DOCKER_REGISTRY: quay.io
QUAYIO_USERNAME: ${{ secrets.quayio_username }}
QUAYIO_PASSWORD: ${{ secrets.quayio_password }}
if: steps.docker-build.outputs.skipped != 'true'
- id: quayio-registry-push
name: Push the image
run: ${{ matrix.build_cmd }} --push-only
env:
DOCKER_REGISTRY: quay.io
if: steps.docker-build.outputs.skipped != 'true'
- id: quayio-registry-logout
name: Logout of the Docker Registry
run: docker logout "${DOCKER_REGISTRY}"
env:
DOCKER_REGISTRY: quay.io
if: steps.docker-build.outputs.skipped != 'true'
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@
[![GitHub license](https://img.shields.io/github/license/netbox-community/netbox-docker)][netbox-docker-license]

[The Github repository](netbox-docker-github) houses the components needed to build Netbox as a Docker container.
Images are built using this code and are released to [Docker Hub][netbox-dockerhub] once a day.
Images are built using this code and are released to [Docker Hub][netbox-dockerhub] and [Quay.io][netbox-quayio] once a day.

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-dockerhub]: https://hub.docker.com/r/netboxcommunity/netbox/
[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
[netbox-quayio]: https://quay.io/repository/netboxcommunity/netbox

## Docker Tags

Expand Down Expand Up @@ -85,11 +86,13 @@ It covers advanced topics such as using files for secrets, deployment to Kuberne

## 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.
Feel free to ask questions in our [Github Community][netbox-community] or join [our Slack channel `#netbox-docker`][netbox-docker-slack] on the [Network To Code Slack][ntc-slack],
which is free to use and where there are almost always people online that can help you in the Slack channel.

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.

[netbox-community]: https://github.com/netbox-community/netbox-docker/discussions

## Dependencies

This project relies only on *Docker* and *docker-compose* meeting these requirements:
Expand All @@ -104,7 +107,7 @@ To check the version installed on your system run `docker --version` and `docker
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 `netboxcommunity/netbox` Docker image on Docker Hub][netbox-dockerhub].
[any tag of the `netboxcommunity/netbox` Docker image on Docker Hub][netbox-dockerhub] or [Quay.io][netbox-quayio].

```bash
export VERSION=v2.7.1
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.26.2
0.27.0
4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then
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 " Default: 'python:3.9-alpine'"
echo " DOCKER_TARGET A specific target to build."
echo " It's currently not possible to pass multiple targets."
echo " Default: main ldap"
Expand Down Expand Up @@ -157,7 +157,7 @@ fi
# Determining the value for DOCKER_FROM
###
if [ -z "$DOCKER_FROM" ]; then
DOCKER_FROM="python:3.8-alpine"
DOCKER_FROM="python:3.9-alpine"
fi

###
Expand Down
4 changes: 2 additions & 2 deletions configuration/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def _read_secret(secret_name, default = None):

# 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)
LOGIN_TIMEOUT = int(environ.get('LOGIN_TIMEOUT', 1209600))

# Setting this to True will display a "maintenance mode" banner at the top of every page.
MAINTENANCE_MODE = environ.get('MAINTENANCE_MODE', 'False').lower() == 'true'
Expand Down Expand Up @@ -233,7 +233,7 @@ def _read_secret(secret_name, default = None):
# 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)
SESSION_FILE_PATH = environ.get('SESSIONS_ROOT', None)

# Time zone (default: UTC)
TIME_ZONE = environ.get('TIME_ZONE', 'UTC')
Expand Down
15 changes: 9 additions & 6 deletions configuration/ldap/ldap_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@ def _import_group_type(group_type_name):
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', '')
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', '')
}
AUTH_LDAP_USER_FLAGS_BY_GROUP = {}

if AUTH_LDAP_REQUIRE_GROUP is not None:
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'
Expand Down
26 changes: 11 additions & 15 deletions initializers/custom_fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,16 @@
# required: false
# filter_logic: exact
# weight: 30
# default: First Item
# on_objects:
# - dcim.models.Device
# choices:
# - value: First Item
# weight: 10
# - value: Second Item
# weight: 20
# - value: Third Item
# weight: 30
# - value: Fifth Item
# weight: 50
# - value: Fourth Item
# weight: 40
# select_field_auto_weight:
# - First Item
# - Second Item
# - Third Item
# - Fifth Item
# - Fourth Item
# select_field_legacy_format:
# type: select
# label: Choose between items
# required: false
Expand All @@ -65,9 +61,9 @@
# on_objects:
# - dcim.models.Device
# choices:
# - value: A
# - value: B
# - value: C
# - value: A # this is the deprecated format.
# - value: B # we only use it for the tests.
# - value: C # please see above for the new format.
# - value: "D like deprecated"
# weight: 999
# - value: E
Expand All @@ -76,7 +72,7 @@
# label: Yes Or No?
# required: true
# filter_logic: loose
# default: "false" # important: but "false" in quotes!
# default: "false" # important: put "false" in quotes!
# weight: 90
# on_objects:
# - dcim.models.Device
Expand Down
8 changes: 4 additions & 4 deletions initializers/device_types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
# manufacturer: Manufacturer 1
# slug: model-1
# u_height: 2
# custom_fields:
# custom_field_data:
# text_field: Description
# - model: Model 2
# manufacturer: Manufacturer 1
# slug: model-2
# custom_fields:
# custom_field_data:
# text_field: Description
# - model: Model 3
# manufacturer: Manufacturer 1
# slug: model-3
# is_full_depth: false
# u_height: 0
# custom_fields:
# custom_field_data:
# text_field: Description
# - model: Other
# manufacturer: No Name
# slug: other
# custom_fields:
# custom_field_data:
# text_field: Description
6 changes: 3 additions & 3 deletions initializers/devices.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# rack: rack-01
# face: front
# position: 1
# custom_fields:
# custom_field_data:
# text_field: Description
# - name: server02
# device_role: server
Expand All @@ -31,7 +31,7 @@
# position: 2
# primary_ip4: 10.1.1.2/24
# primary_ip6: 2001:db8:a000:1::2/64
# custom_fields:
# custom_field_data:
# text_field: Description
# - name: server03
# device_role: server
Expand All @@ -40,5 +40,5 @@
# rack: rack-03
# face: front
# position: 3
# custom_fields:
# custom_field_data:
# text_field: Description
6 changes: 3 additions & 3 deletions initializers/racks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# custom_field_data:
# text_field: Description
# - site: AMS 2
# name: rack-02
# role: Role 2
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# custom_field_data:
# text_field: Description
# - site: SING 1
# name: rack-03
Expand All @@ -37,5 +37,5 @@
# type: 4-post-cabinet
# width: 19
# u_height: 47
# custom_fields:
# custom_field_data:
# text_field: Description
16 changes: 8 additions & 8 deletions initializers/sites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@
# status: active
# facility: Amsterdam 1
# asn: 12345
# custom_fields:
# text_field: Description
# custom_field_data:
# text_field: Description for AMS1
# - name: AMS 2
# slug: ams2
# region: Downtown
# status: active
# facility: Amsterdam 2
# asn: 54321
# custom_fields:
# text_field: Description
# custom_field_data:
# text_field: Description for AMS2
# - name: AMS 3
# slug: ams3
# region: Suburbs
# status: active
# facility: Amsterdam 3
# asn: 67890
# custom_fields:
# text_field: Description
# custom_field_data:
# text_field: Description for AMS3
# - name: SING 1
# slug: sing1
# region: Singapore
# status: active
# facility: Singapore 1
# asn: 09876
# custom_fields:
# text_field: Description
# custom_field_data:
# text_field: Description for SING1
2 changes: 1 addition & 1 deletion startup_scripts/000_users.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys

from django.contrib.auth.models import Group, User
from django.contrib.auth.models import User
from startup_script_utils import load_yaml, set_permissions
from users.models import Token

Expand Down
36 changes: 20 additions & 16 deletions startup_scripts/020_custom_fields.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from extras.models import CustomField, CustomFieldChoice
import sys

from extras.models import CustomField
from startup_script_utils import load_yaml
import sys

def get_class_for_class_path(class_path):
import importlib
Expand All @@ -21,34 +21,38 @@ def get_class_for_class_path(class_path):
custom_field, created = CustomField.objects.get_or_create(name = cf_name)

if created:
if cf_details.get('default', 0):
if cf_details.get('default', False):
custom_field.default = cf_details['default']

if cf_details.get('description', 0):
if cf_details.get('description', False):
custom_field.description = cf_details['description']

if cf_details.get('label', 0):
if cf_details.get('label', False):
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))
custom_field.content_types.add(get_class_for_class_path(object_type))

if cf_details.get('required', 0):
if cf_details.get('required', False):
custom_field.required = cf_details['required']

if cf_details.get('type', 0):
if cf_details.get('type', False):
custom_field.type = cf_details['type']

if cf_details.get('weight', 0):
if cf_details.get('weight', -1) >= 0:
custom_field.weight = cf_details['weight']

custom_field.save()
if cf_details.get('choices', False):
custom_field.choices = []

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}
)
for choice_detail in cf_details.get('choices', []):
if isinstance(choice_detail, dict) and 'value' in choice_detail:
# legacy mode
print(f"⚠️ Please migrate the choice '{choice_detail['value']}' of '{cf_name}' to the new format, as 'weight' is no longer supported!")
custom_field.choices.append(choice_detail['value'])
else:
custom_field.choices.append(choice_detail)

custom_field.save()

print("🔧 Created custom field", cf_name)
Loading

0 comments on commit aa4d630

Please sign in to comment.