From 64b763429f5ad8b4b9db69a9896869473ffe570d Mon Sep 17 00:00:00 2001 From: Ryan Merolle Date: Wed, 1 Apr 2020 23:41:35 -0400 Subject: [PATCH 01/22] update configuration.py for netbox 2.7.11 REDIS config update configuration.py to use REDIS config referencing `tasks` in place of `webhooks` --- configuration/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/configuration.py b/configuration/configuration.py index af5d3ba..9ebbff0 100644 --- a/configuration/configuration.py +++ b/configuration/configuration.py @@ -51,7 +51,7 @@ SECRET_KEY = os.environ.get('SECRET_KEY', read_secret('secret_key')) # Redis database settings. The Redis database is used for caching and background processing such as webhooks REDIS = { - 'webhooks': { + 'tasks': { 'HOST': os.environ.get('REDIS_HOST', 'localhost'), 'PORT': int(os.environ.get('REDIS_PORT', 6379)), 'PASSWORD': os.environ.get('REDIS_PASSWORD', read_secret('redis_password')), From 26d08302e3e11c2101acb50816da160209ca90cd Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Sat, 4 Apr 2020 10:14:36 +0200 Subject: [PATCH 02/22] 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. --- build.sh | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/build.sh b/build.sh index 82a6e34..051cffb 100755 --- a/build.sh +++ b/build.sh @@ -247,29 +247,27 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do fi # --label - if [ "${DOCKER_TARGET}" == "main" ]; then + DOCKER_BUILD_ARGS+=( + --label "ORIGINAL_TAG=${TARGET_DOCKER_TAG}" + + --label "org.label-schema.build-date=${BUILD_DATE}" + --label "org.opencontainers.image.created=${BUILD_DATE}" + + --label "org.label-schema.version=${PROJECT_VERSION}" + --label "org.opencontainers.image.version=${PROJECT_VERSION}" + ) + if [ -d ".git" ]; then DOCKER_BUILD_ARGS+=( - --label "ORIGINAL_TAG=${TARGET_DOCKER_TAG}" - - --label "org.label-schema.build-date=${BUILD_DATE}" - --label "org.opencontainers.image.created=${BUILD_DATE}" - - --label "org.label-schema.version=${PROJECT_VERSION}" - --label "org.opencontainers.image.version=${PROJECT_VERSION}" + --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}" ) - 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 fi # --build-arg @@ -298,7 +296,9 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # Pushing the docker images if either `--push` or `--push-only` are passed ### if [ "${2}" == "--push" ] || [ "${2}" == "--push-only" ] ; then - echo "⏫ Pushing '${TARGET_DOCKER_TAG}" + echo "⏫ Inspecting labels on '${TARGET_DOCKER_TAG}'" + $DRY docker inspect "${TARGET_DOCKER_TAG}" --format "{{json .Config.Labels}}" + echo "⏫ Pushing '${TARGET_DOCKER_TAG}'" $DRY docker push "${TARGET_DOCKER_TAG}" echo "✅ Finished pushing the Docker image '${TARGET_DOCKER_TAG}'." From 8e34f46bad21d9467a8e5c24b7b31350e8a0deaf Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 8 Apr 2020 15:45:56 +0200 Subject: [PATCH 03/22] 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. --- Dockerfile | 2 +- build-functions/get-public-image-config.sh | 77 ++++++++++++++++++++++ build.sh | 66 +++++++++++++++++-- 3 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 build-functions/get-public-image-config.sh diff --git a/Dockerfile b/Dockerfile index 7764248..e167a62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG FROM=python:3.7-alpine +ARG FROM FROM ${FROM} as builder RUN apk add --no-cache \ diff --git a/build-functions/get-public-image-config.sh b/build-functions/get-public-image-config.sh new file mode 100644 index 0000000..d207766 --- /dev/null +++ b/build-functions/get-public-image-config.sh @@ -0,0 +1,77 @@ +#!/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=$(_get_token $image) + local 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=$(_get_token $image) + _get_layers $image $tag $token +} + +get_image_last_layer() { + local image=$1 + local tag=$2 + local token=$(_get_token $image) + local 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' +} diff --git a/build.sh b/build.sh index 051cffb..5939e63 100755 --- a/build.sh +++ b/build.sh @@ -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: Whatever is defined as default in the Dockerfile." + echo " Default: 'python:3.7-alpine'" echo " DOCKER_TARGET A specific target to build." echo " It's currently not possible to pass multiple targets." echo " Default: main ldap" @@ -153,6 +153,11 @@ if [ ! -f "${DOCKERFILE}" ]; then fi fi +### +# Determining the value for DOCKER_FROM +### +DOCKER_FROM="${DOCKER_FROM-python:3.7-alpine}" + ### # Variables for labelling the docker image ### @@ -233,6 +238,49 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # 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" + fi + if [ $DOCKER_REGISTRY = "docker.io" ] && [ $SHOULD_BUILD = "false" ]; 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]}) + 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}) + + 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` ### @@ -269,6 +317,10 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do --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 # --build-arg DOCKER_BUILD_ARGS+=( --build-arg "NETBOX_PATH=${NETBOX_PATH}" ) @@ -287,9 +339,15 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do ### # Building the docker image ### - echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG}'." - $DRY docker build "${DOCKER_BUILD_ARGS[@]}" . - echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG}'" + 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}'" + else + echo "Build skipped because sources didn't change" + echo "::set-output name=skipped::true" + fi fi ### From 794fb45e0eaa9c116d5362b3c758afe153df4bc4 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 8 Apr 2020 16:06:55 +0200 Subject: [PATCH 04/22] Fix shellcheck items found by shellcheck 0.7.1 --- build-functions/get-public-image-config.sh | 25 +++++++++++++--------- build.sh | 20 ++++++++--------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/build-functions/get-public-image-config.sh b/build-functions/get-public-image-config.sh index d207766..f718716 100644 --- a/build-functions/get-public-image-config.sh +++ b/build-functions/get-public-image-config.sh @@ -7,28 +7,33 @@ get_image_label() { local label=$1 local image=$2 local tag=$3 - local token=$(_get_token $image) - local digest=$(_get_digest $image $tag $token) + 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) + if [ "$digest" != "null" ]; then + retval=$(_get_image_configuration "$image" "$token" "$digest" "$label") fi - echo $retval + echo "$retval" } get_image_layers() { local image=$1 local tag=$2 - local token=$(_get_token $image) - _get_layers $image $tag $token + local token + token=$(_get_token "$image") + _get_layers "$image" "$tag" "$token" } get_image_last_layer() { local image=$1 local tag=$2 - local token=$(_get_token $image) - local layers=($(_get_layers $image $tag $token)) - echo ${layers[-1]} + local token + token=$(_get_token "$image") + local layers + mapfile -t layers < <(_get_layers "$image" "$tag" "$token") + echo "${layers[-1]}" } _get_image_configuration() { diff --git a/build.sh b/build.sh index 5939e63..3592449 100755 --- a/build.sh +++ b/build.sh @@ -172,9 +172,9 @@ PROJECT_VERSION="${PROJECT_VERSION-$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:] # 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) + 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 ### @@ -253,19 +253,19 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do SHOULD_BUILD="true" BUILD_REASON="${BUILD_REASON} interactive" fi - if [ $DOCKER_REGISTRY = "docker.io" ] && [ $SHOULD_BUILD = "false" ]; then + if [ "$DOCKER_REGISTRY" = "docker.io" ] && [ "$SHOULD_BUILD" = "false" ]; then source ./build-functions/get-public-image-config.sh IFS=':' read -ra DOCKER_FROM_SPLIT <<< "${DOCKER_FROM}" - if ! [[ ${DOCKER_FROM_SPLIT[0]} =~ ".*/.*" ]]; then + 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]}) - 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}) + 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}") - if ! printf '%s\n' ${IMAGES_LAYERS_OLD[@]} | grep -q -P "^${PYTHON_LAST_LAYER}\$"; then + if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${PYTHON_LAST_LAYER}\$"; then SHOULD_BUILD="true" BUILD_REASON="${BUILD_REASON} python" fi From a217ce8ffd45fa2b07bba3e3bf1517b58b9c685d Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Wed, 8 Apr 2020 21:38:50 +0200 Subject: [PATCH 05/22] 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. --- .github/workflows/push.yml | 3 ++- .github/workflows/release.yml | 5 +++-- build-branches.sh => build-next.sh | 21 ++++----------------- 3 files changed, 9 insertions(+), 20 deletions(-) rename build-branches.sh => build-next.sh (69%) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4932ae8..d803cbc 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -15,7 +15,8 @@ jobs: build_cmd: - ./build-latest.sh - PRERELEASE=true ./build-latest.sh - - ./build-branches.sh + - ./build-next.sh + - ./build.sh develop docker_from: - '' # use the default of the DOCKERFILE - python:3.7-alpine diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1796097..9dbf770 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,14 +14,15 @@ jobs: build_cmd: - ./build-latest.sh - PRERELEASE=true ./build-latest.sh - - ./build-branches.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@v1 + uses: actions/checkout@v2 - id: docker-build name: Build the image with '${{ matrix.build_cmd }}' run: ${{ matrix.build_cmd }} diff --git a/build-branches.sh b/build-next.sh similarity index 69% rename from build-branches.sh rename to build-next.sh index 483e771..c833d52 100755 --- a/build-branches.sh +++ b/build-next.sh @@ -23,25 +23,12 @@ 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_BRANCHES='map(.name) | .[] | scan("^[^v].+") | match("^(master|develop).*") | .string' +JQ_NEXT='map(.name) | .[] | scan("^[^v].+") | match("^(develop-).*") | .string' CURL="curl -sS" # Querying the Github API to fetch all branches -BRANCHES=$($CURL "${URL_RELEASES}" | jq -r "$JQ_BRANCHES") +NEXT=$($CURL "${URL_RELEASES}" | jq -r "$JQ_NEXT") -### -# Building each branch -### - -# keeping track whether an error occured -ERROR=0 - -# calling build.sh for each branch -for BRANCH in $BRANCHES; do - # shellcheck disable=SC2068 - ./build.sh "${BRANCH}" $@ || ERROR=1 -done - -# returning whether an error occured -exit $ERROR +# shellcheck disable=SC2068 +./build.sh "${NEXT}" $@ From d84c399c00f6b58a84a34f7a2f2f8e7ab59eaa74 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 9 Apr 2020 08:17:05 +0200 Subject: [PATCH 06/22] Let "latest" tag follow the highest version Latest tag is now added to the new version when it is release by Netbox. --- build-functions/docker-functions.sh | 8 ++++++++ build.sh | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 build-functions/docker-functions.sh diff --git a/build-functions/docker-functions.sh b/build-functions/docker-functions.sh new file mode 100644 index 0000000..137ec54 --- /dev/null +++ b/build-functions/docker-functions.sh @@ -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}'." +} \ No newline at end of file diff --git a/build.sh b/build.sh index 3592449..e170d9e 100755 --- a/build.sh +++ b/build.sh @@ -222,15 +222,18 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # 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="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 @@ -292,6 +295,7 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do ) if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then DOCKER_BUILD_ARGS+=( -t "${TARGET_DOCKER_SHORT_TAG}" ) + DOCKER_BUILD_ARGS+=( -t "${TARGET_DOCKER_LATEST_TAG}" ) fi # --label @@ -344,6 +348,8 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do 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" @@ -354,16 +360,12 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # Pushing the docker images if either `--push` or `--push-only` are passed ### if [ "${2}" == "--push" ] || [ "${2}" == "--push-only" ] ; then - echo "⏫ Inspecting labels on '${TARGET_DOCKER_TAG}'" - $DRY docker inspect "${TARGET_DOCKER_TAG}" --format "{{json .Config.Labels}}" - echo "⏫ Pushing '${TARGET_DOCKER_TAG}'" - $DRY docker push "${TARGET_DOCKER_TAG}" - echo "✅ Finished pushing the Docker image '${TARGET_DOCKER_TAG}'." + source ./build-functions/docker-functions.sh + push_image_to_registry "${TARGET_DOCKER_TAG}" if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then - echo "⏫ Pushing '${TARGET_DOCKER_SHORT_TAG}'" - $DRY docker push "${TARGET_DOCKER_SHORT_TAG}" - echo "✅ Finished pushing the Docker image '${TARGET_DOCKER_SHORT_TAG}'." + push_image_to_registry "${TARGET_DOCKER_SHORT_TAG}" + push_image_to_registry "${TARGET_DOCKER_LATEST_TAG}" fi fi done From 9ea95950b96690ee35dec17188888cf27e8b4be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Tue, 7 Apr 2020 12:46:57 +0200 Subject: [PATCH 07/22] probot/no-response configuration --- .github/no-response.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/no-response.yml diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000..1a7a45a --- /dev/null +++ b/.github/no-response.yml @@ -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. From 231de236e0c4853093e722e8007cb90c9db69d9d Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 9 Apr 2020 08:47:07 +0200 Subject: [PATCH 08/22] Removed Travis CI configuration and script We are no longer building the images with Travis CI. --- .travis.yml | 32 -------------------------------- build-all.sh | 51 --------------------------------------------------- 2 files changed, 83 deletions(-) delete mode 100644 .travis.yml delete mode 100755 build-all.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 99c5b53..0000000 --- a/.travis.yml +++ /dev/null @@ -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= diff --git a/build-all.sh b/build-all.sh deleted file mode 100755 index 462a83a..0000000 --- a/build-all.sh +++ /dev/null @@ -1,51 +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[*]}" - -if [ -n "${DEBUG}" ]; then - export DEBUG -fi - -ERROR=0 - -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 - ;; - *) - 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 - -exit $ERROR From 5909670690a362eb51b2d0ea2e16e114c482de89 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 9 Apr 2020 09:04:20 +0200 Subject: [PATCH 09/22] Fixed "latest" tag The variable for the latest tag didn't contain all the needed values. --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index e170d9e..ab29a33 100755 --- a/build.sh +++ b/build.sh @@ -229,7 +229,7 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do MINOR=${BASH_REMATCH[2]} TARGET_DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-${DOCKER_REGISTRY}/${DOCKER_ORG}/${DOCKER_REPO}:v${MAJOR}.${MINOR}}" - TARGET_DOCKER_LATEST_TAG="latest" + 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}" From 786f9b50d2892cf942d1fcaca94fbedf0e00e8a3 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 9 Apr 2020 10:26:21 +0200 Subject: [PATCH 10/22] 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 --- build.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index ab29a33..68f2f82 100755 --- a/build.sh +++ b/build.sh @@ -156,7 +156,9 @@ fi ### # Determining the value for DOCKER_FROM ### -DOCKER_FROM="${DOCKER_FROM-python:3.7-alpine}" +if [ -z "$DOCKER_FROM"]; then + DOCKER_FROM="python:3.7-alpine" +fi ### # Variables for labelling the docker image From 7fb78b3fd2856cb804319506f0091fece75d368a Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Mon, 13 Apr 2020 21:23:50 +0200 Subject: [PATCH 11/22] Fixed script in case no branch for next exists Build now prints a message when no devlop-* branch is found instead of crashing --- build-next.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build-next.sh b/build-next.sh index c833d52..f134333 100755 --- a/build-next.sh +++ b/build-next.sh @@ -30,5 +30,10 @@ CURL="curl -sS" # Querying the Github API to fetch all branches NEXT=$($CURL "${URL_RELEASES}" | jq -r "$JQ_NEXT") -# shellcheck disable=SC2068 -./build.sh "${NEXT}" $@ +if [ -n "$NEXT" ]; then + # shellcheck disable=SC2068 + ./build.sh "${NEXT}" $@ +else + echo "No branch matching 'develop-*' found" + echo "::set-output name=skipped::true" +fi From 1c65f7af10aeb392a5f9012c6dd66e301700c80b Mon Sep 17 00:00:00 2001 From: ibeljakov Date: Sat, 18 Apr 2020 17:08:42 +0300 Subject: [PATCH 12/22] Dockerfile: Fixed file permissions for media --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7764248..2c83172 100644 --- a/Dockerfile +++ b/Dockerfile @@ -75,7 +75,7 @@ WORKDIR /opt/netbox/netbox # 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 g+w static media +RUN mkdir static && chmod -R g+w static media ENTRYPOINT [ "/opt/netbox/docker-entrypoint.sh" ] From d6323ce40f811ae02b2d71280801aec1d3dee131 Mon Sep 17 00:00:00 2001 From: Hoanh An Date: Wed, 22 Apr 2020 16:24:34 -0400 Subject: [PATCH 13/22] Fix typo in overriding docker-compose config --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1919dfa..375eb36 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ There is a more complete [_Getting Started_ guide on our wiki][wiki-getting-star ```bash git clone -b release https://github.com/netbox-community/netbox-docker.git cd netbox-docker -tee netbox-docker.override.yml < Date: Mon, 11 May 2020 16:46:10 +0300 Subject: [PATCH 14/22] Fixed devices.py.example report --- reports/devices.py.example | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reports/devices.py.example b/reports/devices.py.example index 2dee036..670eeb6 100644 --- a/reports/devices.py.example +++ b/reports/devices.py.example @@ -1,4 +1,4 @@ -from dcim.constants import CONNECTION_STATUS_PLANNED, DEVICE_STATUS_ACTIVE +from dcim.choices import DeviceStatusChoices from dcim.models import ConsolePort, Device, PowerPort from extras.reports import Report @@ -9,13 +9,14 @@ class DeviceConnectionsReport(Report): def test_console_connection(self): # Check that every console port for every active device has a connection defined. - for console_port in ConsolePort.objects.select_related('device').filter(device__status=DEVICE_STATUS_ACTIVE): + 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 console_port.connection_status == CONNECTION_STATUS_PLANNED: + elif not console_port.connection_status: self.log_warning( console_port.device, "Console connection for {} marked as planned".format(console_port.name) @@ -26,12 +27,12 @@ class DeviceConnectionsReport(Report): def test_power_connections(self): # Check that every active device has at least two connected power supplies. - for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE): + 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 power_port.connection_status == CONNECTION_STATUS_PLANNED: + if not power_port.connection_status: self.log_warning( device, "Power connection for {} marked as planned".format(power_port.name) @@ -43,4 +44,3 @@ class DeviceConnectionsReport(Report): ) else: self.log_success(device) - From d8a6c321a15d6deb2b19ebb77455333a4f6ac4ec Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 14 May 2020 13:49:19 +0200 Subject: [PATCH 15/22] Update build.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include suggestion from cimnine Co-authored-by: Christian Mäder --- build.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 68f2f82..1ea4112 100755 --- a/build.sh +++ b/build.sh @@ -257,8 +257,7 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # Asuming non Github builds should always proceed SHOULD_BUILD="true" BUILD_REASON="${BUILD_REASON} interactive" - fi - if [ "$DOCKER_REGISTRY" = "docker.io" ] && [ "$SHOULD_BUILD" = "false" ]; then + elsif [ "$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 From 795e82be46c240aeb3540d853d249f856b19cf75 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Thu, 14 May 2020 13:50:09 +0200 Subject: [PATCH 16/22] Fix shellcheck error --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 1ea4112..7489ebb 100755 --- a/build.sh +++ b/build.sh @@ -156,7 +156,7 @@ fi ### # Determining the value for DOCKER_FROM ### -if [ -z "$DOCKER_FROM"]; then +if [ -z "$DOCKER_FROM" ]; then DOCKER_FROM="python:3.7-alpine" fi @@ -257,7 +257,7 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do # Asuming non Github builds should always proceed SHOULD_BUILD="true" BUILD_REASON="${BUILD_REASON} interactive" - elsif [ "$DOCKER_REGISTRY" = "docker.io" ]; then + 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 From 1bc1ab2a0adb732b270df6f823957b9d7b0ca77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Thu, 14 May 2020 16:19:38 +0200 Subject: [PATCH 17/22] Preserve compatibility --- configuration/configuration.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configuration/configuration.py b/configuration/configuration.py index 9ebbff0..cc438df 100644 --- a/configuration/configuration.py +++ b/configuration/configuration.py @@ -59,6 +59,14 @@ REDIS = { 'DEFAULT_TIMEOUT': int(os.environ.get('REDIS_TIMEOUT', 300)), 'SSL': os.environ.get('REDIS_SSL', 'False').lower() == 'true', }, + 'webhooks': { # legacy setting, can be removed after Netbox seizes support for it + 'HOST': os.environ.get('REDIS_HOST', 'localhost'), + 'PORT': int(os.environ.get('REDIS_PORT', 6379)), + 'PASSWORD': os.environ.get('REDIS_PASSWORD', read_secret('redis_password')), + 'DATABASE': int(os.environ.get('REDIS_DATABASE', 0)), + 'DEFAULT_TIMEOUT': int(os.environ.get('REDIS_TIMEOUT', 300)), + 'SSL': os.environ.get('REDIS_SSL', 'False').lower() == 'true', + }, 'caching': { 'HOST': os.environ.get('REDIS_CACHE_HOST', os.environ.get('REDIS_HOST', 'localhost')), 'PORT': int(os.environ.get('REDIS_CACHE_PORT', os.environ.get('REDIS_PORT', 6379))), From bed40b0d05bc58a30bd026008fad94980052bb55 Mon Sep 17 00:00:00 2001 From: mbchristoff <49072643+mbchristoff@users.noreply.github.com> Date: Thu, 14 May 2020 16:41:42 +0200 Subject: [PATCH 18/22] Add STARTTLS option. (#277) * Add STARTTLS option. --- configuration/ldap_config.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configuration/ldap_config.py b/configuration/ldap_config.py index ba2067c..19277e1 100644 --- a/configuration/ldap_config.py +++ b/configuration/ldap_config.py @@ -37,6 +37,9 @@ AUTH_LDAP_BIND_PASSWORD = os.environ.get('AUTH_LDAP_BIND_PASSWORD', read_secret( # Set a string template that describes any user’s distinguished name based on the username. AUTH_LDAP_USER_DN_TEMPLATE = os.environ.get('AUTH_LDAP_USER_DN_TEMPLATE', None) +# Enable STARTTLS for ldap authentication. +AUTH_LDAP_START_TLS = os.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) From 77feec30a0b6e0fb60a9095ec0259201604b8a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Thu, 14 May 2020 16:02:03 +0200 Subject: [PATCH 19/22] Don't stop when startup_scripts quit Fixes #284 --- startup_scripts/__main__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/startup_scripts/__main__.py b/startup_scripts/__main__.py index b13b8dd..343ca95 100644 --- a/startup_scripts/__main__.py +++ b/startup_scripts/__main__.py @@ -13,6 +13,11 @@ with scandir(dirname(abspath(__file__))) as it: for f in sorted(it, key = filename): if f.name.startswith('__') or not f.is_file(): continue - - print(f"Running {f.path}") - runpy.run_path(f.path) + + print(f"▶️ Running the startup script {f.path}") + try: + runpy.run_path(f.path) + except SystemExit as e: + if e.code is not None and e.code != 0: + print(f"‼️ The startup script {f.path} returned with code {e.code}, exiting.") + raise From ab8ff04852098cafc2f95281fb6e6fe882f50a6d Mon Sep 17 00:00:00 2001 From: Alexander GITTINGS Date: Thu, 14 May 2020 15:09:25 +0000 Subject: [PATCH 20/22] #293 --- configuration/configuration.py | 4 ++++ env/netbox.env | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/configuration/configuration.py b/configuration/configuration.py index af121d9..c07e4dc 100644 --- a/configuration/configuration.py +++ b/configuration/configuration.py @@ -119,6 +119,10 @@ EMAIL = { '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', ''), + 'USE_SSL': os.environ.get('EMAIL_USE_SSL', 'False'), + 'USE_TLS': os.environ.get('EMAIL_USE_TLS', 'False'), + 'SSL_CERTFILE': os.environ.get('EMAIL_SSL_CERTFILE', '') + 'SSL_KEYFILE': os.environ.get('EMAIL_SSL_KEYFILE', '') } # Enforcement of unique IP space can be toggled on a per-VRF basis. diff --git a/env/netbox.env b/env/netbox.env index aaa7482..84184e3 100644 --- a/env/netbox.env +++ b/env/netbox.env @@ -9,6 +9,10 @@ EMAIL_USERNAME=netbox EMAIL_PASSWORD= EMAIL_TIMEOUT=5 EMAIL_FROM=netbox@bar.com +EMAIL_USE_SSL=false +EMAIL_USE_TLS=false +EMAIL_SSL_CERTFILE= +EMAIL_SSL_KEYFILE= MEDIA_ROOT=/opt/netbox/netbox/media NAPALM_USERNAME= NAPALM_PASSWORD= From efec435ba0f33a3c26a1ee63c05457bb2f0bb969 Mon Sep 17 00:00:00 2001 From: Alexander GITTINGS Date: Thu, 14 May 2020 15:37:47 +0000 Subject: [PATCH 21/22] fix some issues --- configuration/configuration.py | 8 ++++---- env/netbox.env | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/configuration/configuration.py b/configuration/configuration.py index c07e4dc..8c8e3d9 100644 --- a/configuration/configuration.py +++ b/configuration/configuration.py @@ -119,10 +119,10 @@ EMAIL = { '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', ''), - 'USE_SSL': os.environ.get('EMAIL_USE_SSL', 'False'), - 'USE_TLS': os.environ.get('EMAIL_USE_TLS', 'False'), - 'SSL_CERTFILE': os.environ.get('EMAIL_SSL_CERTFILE', '') - 'SSL_KEYFILE': os.environ.get('EMAIL_SSL_KEYFILE', '') + 'USE_SSL': os.environ.get('EMAIL_USE_SSL', 'False').lower() == 'true', + 'USE_TLS': os.environ.get('EMAIL_USE_TLS', 'False').lower() == 'true', + 'SSL_CERTFILE': os.environ.get('EMAIL_SSL_CERTFILE', ''), + 'SSL_KEYFILE': os.environ.get('EMAIL_SSL_KEYFILE', ''), } # Enforcement of unique IP space can be toggled on a per-VRF basis. diff --git a/env/netbox.env b/env/netbox.env index 84184e3..9555f93 100644 --- a/env/netbox.env +++ b/env/netbox.env @@ -9,6 +9,7 @@ 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= From 45f7823a1707e7d573abd9fc28507789ed47bda1 Mon Sep 17 00:00:00 2001 From: Tobias Genannt Date: Fri, 15 May 2020 13:59:45 +0200 Subject: [PATCH 22/22] Preparation for 0.24.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ca222b7..2094a10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.23.0 +0.24.0