diff --git a/.bandit.yml b/.bandit.yml index 55c6741b..56f7a83b 100644 --- a/.bandit.yml +++ b/.bandit.yml @@ -3,3 +3,4 @@ skips: [] # No need to check for security issues in the test scripts! exclude_dirs: - "./tests/" + - "./.venv/" diff --git a/.cookiecutter.json b/.cookiecutter.json new file mode 100644 index 00000000..c3d72ff1 --- /dev/null +++ b/.cookiecutter.json @@ -0,0 +1,35 @@ +{ + "cookiecutter": { + "codeowner_github_usernames": "@josh5276 @jvanderaa @progala", + "full_name": "Network to Code, LLC", + "email": "info@networktocode.com", + "github_org": "nautobot", + "plugin_name": "nautobot_device_lifecycle_mgmt", + "verbose_name": "Device Lifecycle Management", + "plugin_slug": "nautobot-device-lifecycle-mgmt", + "project_slug": "nautobot-plugin-device-lifecycle-mgmt", + "repo_url": "https://github.com/nautobot/nautobot-plugin-device-lifecycle-mgmt", + "base_url": "nautobot-device-lifecycle-mgmt", + "min_nautobot_version": "2.0.0", + "max_nautobot_version": "2.9999", + "camel_name": "NautobotDeviceLifecycleManagement", + "project_short_description": "Device Lifecycle Management", + "model_class_name": "None", + "open_source_license": "Apache-2.0", + "docs_base_url": "https://docs.nautobot.com", + "docs_app_url": "https://docs.nautobot.com/projects/device-lifecycle/en/latest", + "_drift_manager": { + "template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", + "template_dir": "nautobot-app", + "template_ref": "develop", + "cookie_dir": "", + "branch_prefix": "drift-manager", + "pull_request_strategy": "create", + "post_actions": [ + "black" + ], + "draft": true, + "baked_commit_ref": "a07609a3fcfaab9b8b2d8d54ce60a293d68d8720" + } + } +} diff --git a/.dockerignore b/.dockerignore index 86f6eac3..2270f496 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,10 +2,26 @@ development/Dockerfile development/docker-compose*.yml development/*.env +*.env +environments/ + +# Python +**/*.pyc +**/*.pyo +**/__pycache__/ +**/.pytest_cache/ +**/.venv/ + # Other +docs/_build FAQ.md +.git/ .gitignore .github tasks.py LICENSE +**/*.log +**/.vscode/ +invoke*.yml +tasks.py diff --git a/.flake8 b/.flake8 index e3ba27d5..c9f5e84d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,10 @@ [flake8] -# E501: Line length is enforced by Black, so flake8 doesn't need to check it -# W503: Black disagrees with this rule, as does PEP 8; Black wins -ignore = E501, W503 +ignore = + E501, # Line length is enforced by Black, so flake8 doesn't need to check it + W503 # Black disagrees with this rule, as does PEP 8; Black wins +exclude = + migrations, + __pycache__, + manage.py, + settings.py, + .venv diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fd91bfb5..12a1e367 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,12 +1,12 @@ --- name: 🐛 Bug Report -about: Report a reproducible bug in the current release of nautobot-plugin-device-lifecycle-mgmt +about: Report a reproducible bug in the current release of nautobot-device-lifecycle-mgmt --- ### Environment -* Python version: -* Nautobot version: -* nautobot-plugin-device-lifecycle-mgmt version: +* Python version: +* Nautobot version: +* nautobot-device-lifecycle-mgmt version: ### Expected Behavior diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 58a26d8d..8f4f4cee 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -5,8 +5,8 @@ about: Propose a new feature or enhancement --- ### Environment -* Nautobot version: -* nautobot-plugin-device-lifecycle-mgmt version: +* Nautobot version: +* nautobot-device-lifecycle-mgmt version: -## Change Notes +# Closes: # -## Justification +## What's Changed + + + +## To Do + + +- [ ] Explanation of Change(s) +- [ ] Added change log fragment(s) (for more information see [the documentation](https://docs.nautobot.com/projects/core/en/stable/development/core/#creating-changelog-fragments)) +- [ ] Attached Screenshots, Payload Example +- [ ] Unit, Integration Tests +- [ ] Documentation Updates (when adding/changing features) +- [ ] Example Plugin Updates (when adding/changing features) +- [ ] Outline Remaining Work, Constraints from Design diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcbdbc41..41f8ec70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,68 +1,85 @@ --- name: "CI" -on: # yamllint disable-line rule:truthy rule:comments - - "push" - - "pull_request" concurrency: # Cancel any existing runs of this workflow for this same PR group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true +on: # yamllint disable-line rule:truthy rule:comments + push: + branches: + - "main" + - "develop" + tags: + - "v*" + pull_request: ~ + env: - PLUGIN_NAME: "nautobot-device-lifecycle-mgmt" + PLUGIN_NAME: "nautobot-plugin-device-lifecycle-mgmt" jobs: black: - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: black" run: "poetry run invoke black" bandit: - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: bandit" run: "poetry run invoke bandit" pydocstyle: - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: pydocstyle" run: "poetry run invoke pydocstyle" flake8: - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: flake8" run: "poetry run invoke flake8" + poetry: + runs-on: "ubuntu-22.04" + env: + INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" + steps: + - name: "Check out repository code" + uses: "actions/checkout@v4" + - name: "Setup environment" + uses: "networktocode/gh-action-setup-poetry-environment@v4" + - name: "Checking: poetry lock file" + run: "poetry run invoke lock --check" yamllint: - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL: "True" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: yamllint" run: "poetry run invoke yamllint" pylint: @@ -70,9 +87,10 @@ jobs: - "bandit" - "pydocstyle" - "flake8" + - "poetry" - "yamllint" - "black" - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" strategy: fail-fast: true matrix: @@ -83,14 +101,14 @@ jobs: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_NAUTOBOT_VER: "${{ matrix.nautobot-version }}" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Set up Docker Buildx" id: "buildx" - uses: "docker/setup-buildx-action@v1" + uses: "docker/setup-buildx-action@v3" - name: "Build" - uses: "docker/build-push-action@v2" + uses: "docker/build-push-action@v5" with: builder: "${{ steps.buildx.outputs.name }}" context: "./" @@ -107,39 +125,80 @@ jobs: run: "cp development/creds.example.env development/creds.env" - name: "Linting: pylint" run: "poetry run invoke pylint" + check-migrations: + needs: + - "bandit" + - "pydocstyle" + - "flake8" + - "poetry" + - "yamllint" + - "black" + runs-on: "ubuntu-22.04" + strategy: + fail-fast: true + matrix: + python-version: ["3.11"] + nautobot-version: ["2.0.0"] + env: + INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_PYTHON_VER: "${{ matrix.python-version }}" + INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_NAUTOBOT_VER: "${{ matrix.nautobot-version }}" + steps: + - name: "Check out repository code" + uses: "actions/checkout@v4" + - name: "Setup environment" + uses: "networktocode/gh-action-setup-poetry-environment@v4" + - name: "Set up Docker Buildx" + id: "buildx" + uses: "docker/setup-buildx-action@v3" + - name: "Build" + uses: "docker/build-push-action@v5" + with: + builder: "${{ steps.buildx.outputs.name }}" + context: "./" + push: false + load: true + tags: "${{ env.PLUGIN_NAME }}/nautobot:${{ matrix.nautobot-version }}-py${{ matrix.python-version }}" + file: "./development/Dockerfile" + cache-from: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}" + cache-to: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}" + build-args: | + NAUTOBOT_VER=${{ matrix.nautobot-version }} + PYTHON_VER=${{ matrix.python-version }} + - name: "Copy credentials" + run: "cp development/creds.example.env development/creds.env" + - name: "Checking: migrations" + run: "poetry run invoke check-migrations" unittest: needs: - "pylint" + - "check-migrations" strategy: fail-fast: true matrix: - python-version: ["3.8"] + python-version: ["3.8", "3.11"] db-backend: ["postgresql"] - nautobot-version: ["2.0.0"] - # The include is a method to limit the amount of jobs ran. This essentially - # means that in addition to standard postgres and stable, also the lowest - # supported version and with mysql + nautobot-version: ["stable"] include: - python-version: "3.11" db-backend: "postgresql" nautobot-version: "2.0.0" - - python-version: "3.11" - db-backend: "postgresql" - nautobot-version: "stable" - runs-on: "ubuntu-20.04" + # - python-version: "3.11" + # db-backend: "mysql" + # nautobot-version: "stable" + runs-on: "ubuntu-22.04" env: INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_PYTHON_VER: "${{ matrix.python-version }}" INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_NAUTOBOT_VER: "${{ matrix.nautobot-version }}" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v2" + uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Set up Docker Buildx" id: "buildx" - uses: "docker/setup-buildx-action@v1" + uses: "docker/setup-buildx-action@v3" - name: "Build" - uses: "docker/build-push-action@v2" + uses: "docker/build-push-action@v5" with: builder: "${{ steps.buildx.outputs.name }}" context: "./" @@ -156,32 +215,28 @@ jobs: run: "cp development/creds.example.env development/creds.env" - name: "Use Mysql invoke settings when needed" run: "cp invoke.mysql.yml invoke.yml" - if: "${{ matrix.db-backend == 'mysql' }}" + if: "matrix.db-backend == 'mysql'" - name: "Run Tests" run: "poetry run invoke unittest" publish_gh: needs: - "unittest" name: "Publish to GitHub" - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" if: "startsWith(github.ref, 'refs/tags/v')" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Set up Python" - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: - python-version: "3.9" + python-version: "3.11" - name: "Install Python Packages" run: "pip install poetry" - name: "Set env" run: "echo RELEASE_VERSION=${GITHUB_REF:10} >> $GITHUB_ENV" - name: "Run Poetry Version" run: "poetry version $RELEASE_VERSION" - - name: "Install Dependencies (needed for mkdocs)" - run: "poetry install" - - name: "Build Documentation" - run: "poetry run mkdocs build --no-directory-urls --strict" - name: "Run Poetry Build" run: "poetry build" - name: "Upload binaries to release" @@ -196,25 +251,21 @@ jobs: needs: - "unittest" name: "Push Package to PyPI" - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" if: "startsWith(github.ref, 'refs/tags/v')" steps: - name: "Check out repository code" - uses: "actions/checkout@v2" + uses: "actions/checkout@v4" - name: "Set up Python" - uses: "actions/setup-python@v2" + uses: "actions/setup-python@v4" with: - python-version: "3.9" + python-version: "3.11" - name: "Install Python Packages" run: "pip install poetry" - name: "Set env" run: "echo RELEASE_VERSION=${GITHUB_REF:10} >> $GITHUB_ENV" - name: "Run Poetry Version" run: "poetry version $RELEASE_VERSION" - - name: "Install Dependencies (needed for mkdocs)" - run: "poetry install" - - name: "Build Documentation" - run: "poetry run mkdocs build --no-directory-urls --strict" - name: "Run Poetry Build" run: "poetry build" - name: "Push to PyPI" @@ -226,9 +277,9 @@ jobs: needs: - "publish_gh" - "publish_pypi" - runs-on: "ubuntu-20.04" + runs-on: "ubuntu-22.04" env: - SLACK_WEBHOOK_URL: "${{ '{{ secrets.SLACK_WEBHOOK_URL }}' }}" + SLACK_WEBHOOK_URL: "${{ secrets.SLACK_WEBHOOK_URL }}" SLACK_MESSAGE: >- *NOTIFICATION: NEW-RELEASE-PUBLISHED*\n Repository: <${{ github.server_url }}/${{ github.repository }}|${{ github.repository }}>\n @@ -238,11 +289,12 @@ jobs: - name: "Send a notification to Slack" # ENVs cannot be used directly in job.if. This is a workaround to check # if SLACK_WEBHOOK_URL is present. - if: "${{ env.SLACK_WEBHOOK_URL != '' }}" - uses: "slackapi/slack-github-action@v1.17.0" + if: "env.SLACK_WEBHOOK_URL != ''" + uses: "slackapi/slack-github-action@v1" with: payload: | { + "text": "${{ env.SLACK_MESSAGE }}", "blocks": [ { "type": "section", diff --git a/.github/workflows/rebake.yml b/.github/workflows/rebake.yml new file mode 100644 index 00000000..13d1e3a0 --- /dev/null +++ b/.github/workflows/rebake.yml @@ -0,0 +1,118 @@ +--- +name: "Rebake Cookie" +on: # yamllint disable-line rule:truthy + workflow_call: + inputs: + cookie: + description: "The cookie to rebake" + type: "string" + default: "" + draft: + description: "Whether to create the pull request as a draft" + type: "string" + default: "" + pull-request: + description: "The pull request strategy" + type: "string" + default: "" + template: + description: "The template repository URL" + type: "string" + default: "" + template-dir: + description: "The directory within the template repository to use as the template" + type: "string" + default: "" + template-ref: + description: "The branch or tag to use for the template" + type: "string" + default: "" + drift-manager-tag: + description: "The drift manager Docker image tag to use" + type: "string" + default: "latest" + workflow_dispatch: + inputs: + cookie: + description: "The cookie to rebake" + type: "string" + default: "" + draft: + description: "Whether to create the pull request as a draft" + type: "string" + default: "" + pull-request: + description: "The pull request strategy" + type: "string" + default: "" + template: + description: "The template repository URL" + type: "string" + default: "" + template-dir: + description: "The directory within the template repository to use as the template" + type: "string" + default: "" + template-ref: + description: "The branch or tag to use for the template" + type: "string" + default: "" + drift-manager-tag: + description: "The drift manager Docker image tag to use" + type: "string" + default: "latest" +jobs: + rebake: + runs-on: "ubuntu-22.04" + permissions: + actions: "write" + contents: "write" + packages: "read" + pull-requests: "write" + container: "ghcr.io/nautobot/cookiecutter-nautobot-app-drift-manager/prod:${{ github.event.inputs.drift-manager-tag }}" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + steps: + - name: "Configure Rebake Arguments" + id: "config" + shell: "bash" + run: | + ARGS='--push' + + if [[ '${{ github.event.inputs.draft }}' == 'true' ]]; then + ARGS="$ARGS --draft" + elif [[ '${{ github.event.inputs.draft }}' == 'false' ]]; then + ARGS="$ARGS --no-draft" + elif [[ '${{ github.event.inputs.draft }}' == '' ]]; then + echo "Using repo default value for --draft" + else + echo "ERROR: Invalid value for draft: '${{ github.event.inputs.draft }}'" + exit 1 + fi + + if [[ '${{ github.event.inputs.pull-request }}' != '' ]]; then + ARGS="$ARGS --pull-request='${{ github.event.inputs.pull-request }}'" + fi + + if [[ '${{ github.event.inputs.template }}' != '' ]]; then + ARGS="$ARGS --template='${{ github.event.inputs.template }}'" + fi + + if [[ '${{ github.event.inputs.template-dir }}' != '' ]]; then + ARGS="$ARGS --template-dir='${{ github.event.inputs.template-dir }}'" + fi + + if [[ '${{ github.event.inputs.template-ref }}' != '' ]]; then + ARGS="$ARGS --template-ref='${{ github.event.inputs.template-ref }}'" + fi + + if [[ '${{ github.event.inputs.cookie }}' == '' ]]; then + ARGS="$ARGS '${{ github.repositoryUrl }}'" + else + ARGS="$ARGS '${{ github.event.inputs.cookie }}'" + fi + + echo "args=$ARGS" >> $GITHUB_OUTPUT + - name: "Rebake" + run: | + python -m ntc_cookie_drift_manager rebake ${{ steps.config.outputs.args }} diff --git a/.github/workflows/upstream_testing.yml b/.github/workflows/upstream_testing.yml index 784106f1..e0a88bba 100644 --- a/.github/workflows/upstream_testing.yml +++ b/.github/workflows/upstream_testing.yml @@ -10,4 +10,4 @@ jobs: uses: "nautobot/nautobot/.github/workflows/plugin_upstream_testing_base.yml@develop" with: # Below could potentially be collapsed into a single argument if a concrete relationship between both is enforced invoke_context_name: "NAUTOBOT_DEVICE_LIFECYCLE_MGMT" - plugin_name: "nautobot-device-lifecycle-mgmt" + plugin_name: "nautobot-plugin-device-lifecycle-mgmt" diff --git a/.gitignore b/.gitignore index 74a3bacc..bb6b5ace 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,3 @@ -# Package specific ignores -development/creds.env -loader - # Ansible Retry Files *.retry @@ -197,8 +193,27 @@ $RECYCLE.BIN/ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff -.idea/ - +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries # Gradle and Maven with auto-import # When using Gradle or Maven with auto-import, you should exclude module files, @@ -281,10 +296,14 @@ fabric.properties *.code-workspace # Rando -docker-compose.override.yml -override.env +creds.env +development/*.txt + +# Invoke overrides invoke.yml -*.dccache -# MKDocs Build -nautobot_device_lifecycle_mgmt/static/nautobot_device_lifecycle_mgmt/docs +# Docs +public +/compose.yaml +/dump.sql +/nautobot_device_lifecycle_mgmt/static/nautobot_device_lifecycle_mgmt/docs diff --git a/.readthedocs.yaml b/.readthedocs.yaml index a9d358ef..9a0a64c7 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -14,7 +14,7 @@ build: mkdocs: configuration: "mkdocs.yml" - # fail_on_warning: true + fail_on_warning: true # Use our docs/requirements.txt during installation. python: diff --git a/.yamllint.yml b/.yamllint.yml index d169938a..c7d84952 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -8,5 +8,6 @@ rules: line-length: "disable" quoted-strings: quote-type: "double" - brackets: - max-spaces-inside: 1 +ignore: | + .venv/ + compose.yaml diff --git a/LICENSE b/LICENSE index 087f92f5..d46cc975 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Apache Software License 2.0 -Copyright (c) 2021, Network to Code, LLC +Copyright (c) 2023, Network to Code, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/development/Dockerfile b/development/Dockerfile index 9e3f6c24..3245cbf3 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -9,8 +9,8 @@ # Accepts a desired Nautobot version as build argument, default to 2.0.0 ARG NAUTOBOT_VER="2.0.0" -# Accepts a desired Python version as build argument, default to 3.10 -ARG PYTHON_VER="3.10" +# Accepts a desired Python version as build argument, default to 3.11 +ARG PYTHON_VER="3.11" # Retrieve published development image of Nautobot base which should include most CI dependencies FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} @@ -19,14 +19,15 @@ FROM ghcr.io/nautobot/nautobot-dev:${NAUTOBOT_VER}-py${PYTHON_VER} ARG NAUTOBOT_ROOT=/opt/nautobot ENV prometheus_multiproc_dir=/prom_cache -ENV NAUTOBOT_ROOT ${NAUTOBOT_ROOT} +ENV NAUTOBOT_ROOT=${NAUTOBOT_ROOT} +ENV INVOKE_NAUTOBOT_DEVICE_LIFECYCLE_MGMT_LOCAL=true # Install Poetry manually via its installer script; # We might be using an older version of Nautobot that includes an older version of Poetry # and CI and local development may have a newer version of Poetry # Since this is only used for development and we don't ship this container, pinning Poetry back is not expressly necessary # We also don't need virtual environments in container -RUN curl -sSL https://install.python-poetry.org | python3 - && \ +RUN which poetry || curl -sSL https://install.python-poetry.org | python3 - && \ poetry config virtualenvs.create false # !!! USE CAUTION WHEN MODIFYING LINES ABOVE @@ -68,14 +69,13 @@ RUN sort poetry_freeze_base.txt poetry_freeze_all.txt | uniq -u > poetry_freeze_ # Install all local project as editable, constrained on Nautobot version, to get any additional # direct dependencies of the app -RUN pip install -c constraints.txt -e . +RUN --mount=type=cache,target="/root/.cache/pip",sharing=locked \ + pip install -c constraints.txt -e .[all] # Install any dev dependencies frozen from Poetry # Can be improved in Poetry 1.2 which allows `poetry install --only dev` -RUN pip install -c constraints.txt -r poetry_freeze_dev.txt +RUN --mount=type=cache,target="/root/.cache/pip",sharing=locked \ + pip install -c constraints.txt -r poetry_freeze_dev.txt COPY development/nautobot_config.py ${NAUTOBOT_ROOT}/nautobot_config.py # !!! USE CAUTION WHEN MODIFYING LINES ABOVE - -# With USER nautobot Coverage is unable to write to /source which is a locally mounted volume -USER root diff --git a/development/creds.example.env b/development/creds.example.env index db6ad546..26e24fad 100644 --- a/development/creds.example.env +++ b/development/creds.example.env @@ -2,23 +2,26 @@ # CREDS File: Store private information. Copied to creds.env and always ignored ################################################################################ # Nautobot Configuration Secret Items -SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj NAUTOBOT_CREATE_SUPERUSER=true -NAUTOBOT_SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567 +NAUTOBOT_DB_PASSWORD=changeme +NAUTOBOT_NAPALM_USERNAME='' +NAUTOBOT_NAPALM_PASSWORD='' +NAUTOBOT_REDIS_PASSWORD=changeme +NAUTOBOT_SECRET_KEY='changeme' +NAUTOBOT_SUPERUSER_NAME=admin +NAUTOBOT_SUPERUSER_EMAIL=admin@example.com NAUTOBOT_SUPERUSER_PASSWORD=admin +NAUTOBOT_SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567 -# Nauotbot DB Password to connect to the backend -# - NOTE: Should be the same as the selected backend (MySQL or Postgres password) -NAUTOBOT_DB_PASSWORD=notverysecurepwd +# Postgres +POSTGRES_PASSWORD=${NAUTOBOT_DB_PASSWORD} +PGPASSWORD=${NAUTOBOT_DB_PASSWORD} # MySQL Credentials -MYSQL_ROOT_PASSWORD=notverysecurepwd -MYSQL_PASSWORD=notverysecurepwd - -# Postgres Credentials -POSTGRES_PASSWORD=notverysecurepwd +MYSQL_ROOT_PASSWORD=${NAUTOBOT_DB_PASSWORD} +MYSQL_PASSWORD=${NAUTOBOT_DB_PASSWORD} -# Redis Credentials -REDIS_PASSWORD=notverysecurepwd -NAUTOBOT_REDIS_PASSWORD=${REDIS_PASSWORD} -NAUTOBOT_LOG_LEVEL=DEBUG +# Use these to override values in development.env +# NAUTOBOT_DB_HOST=localhost +# NAUTOBOT_REDIS_HOST=localhost +# NAUTOBOT_CONFIG=development/nautobot_config.py diff --git a/development/dev.env b/development/development.env similarity index 58% rename from development/dev.env rename to development/development.env index a881be51..54f0b870 100644 --- a/development/dev.env +++ b/development/development.env @@ -2,47 +2,37 @@ # DEV File: Store environment information. NOTE: Secrets NOT stored here! ################################################################################ # Nautobot Configuration Environment Variables -ALLOWED_HOSTS=* -BANNER_TOP="Local" +NAUTOBOT_ALLOWED_HOSTS=* +NAUTOBOT_BANNER_TOP="Local" NAUTOBOT_CHANGELOG_RETENTION=0 -NAUTOBOT_ROOT=/opt/nautobot + NAUTOBOT_DEBUG=True -NAUTOBOT_DJANGO_EXTENSIONS_ENABLED=True -NAUTOBOT_DJANGO_TOOLBAR_ENABLED=True NAUTOBOT_LOG_LEVEL=DEBUG -NAUTOBOT_MAX_PAGE_SIZE=1000 NAUTOBOT_METRICS_ENABLED=True NAUTOBOT_NAPALM_TIMEOUT=5 +NAUTOBOT_MAX_PAGE_SIZE=0 # Redis Configuration Environment Variables -REDIS_HOST=redis -NAUTOBOT_REDIS_HOST=${REDIS_HOST} +NAUTOBOT_REDIS_HOST=redis NAUTOBOT_REDIS_PORT=6379 # Uncomment NAUTOBOT_REDIS_SSL if using SSL # NAUTOBOT_REDIS_SSL=True -SUPERUSER_EMAIL=admin@example.com -SUPERUSER_NAME=admin - # Nautobot DB Connection Environment Variables -NAUTOBOT_DB_HOST=db NAUTOBOT_DB_NAME=nautobot NAUTOBOT_DB_USER=nautobot +NAUTOBOT_DB_HOST=db NAUTOBOT_DB_TIMEOUT=300 -# Uncomment the environment variables that related to your DB backend. -NAUTOBOT_DB_ENGINE=django.db.backends.postgresql -NAUTOBOT_DB_PORT=5432 -# NAUTOBOT_DB_ENGINE=django.db.backends.mysql -# NAUTOBOT_DB_PORT=3306 +# Use them to overwrite the defaults in nautobot_config.py +# NAUTOBOT_DB_ENGINE=django.db.backends.postgresql +# NAUTOBOT_DB_PORT=5432 # Needed for Postgres should match the values for Nautobot above -POSTGRES_DB=nautobot -POSTGRES_USER=nautobot -PGUSER=nautobot -POSTGRES_HOST=postgres +POSTGRES_USER=${NAUTOBOT_DB_USER} +POSTGRES_DB=${NAUTOBOT_DB_NAME} # Needed for MYSQL should match the values for Nautobot above -MYSQL_DATABASE=nautobot -MYSQL_USER=nautobot +MYSQL_USER=${NAUTOBOT_DB_USER} +MYSQL_DATABASE=${NAUTOBOT_DB_NAME} MYSQL_ROOT_HOST=% diff --git a/development/development_mysql.env b/development/development_mysql.env new file mode 100644 index 00000000..b01fc8ab --- /dev/null +++ b/development/development_mysql.env @@ -0,0 +1,3 @@ +# Custom ENVs for Mysql +# Due to docker image limitations for Mysql, we need "root" user to create more than one database table +NAUTOBOT_DB_USER=root diff --git a/development/docker-compose.base.yml b/development/docker-compose.base.yml index 0f2525bb..d3ac303e 100644 --- a/development/docker-compose.base.yml +++ b/development/docker-compose.base.yml @@ -1,60 +1,50 @@ --- -x-nautobot-build: - &nautobot-build +x-nautobot-build: &nautobot-build build: args: NAUTOBOT_VER: "${NAUTOBOT_VER}" PYTHON_VER: "${PYTHON_VER}" context: "../" dockerfile: "development/Dockerfile" -x-nautobot-base: - &nautobot-base +x-nautobot-base: &nautobot-base image: "nautobot-device-lifecycle-mgmt/nautobot:${NAUTOBOT_VER}-py${PYTHON_VER}" env_file: - - "dev.env" + - "development.env" - "creds.env" tty: true -version: "3.4" +version: "3.8" services: nautobot: - ports: - - "0.0.0.0:8080:8080" depends_on: redis: condition: "service_started" db: condition: "service_healthy" - <<: [ *nautobot-build, *nautobot-base ] - celery_worker: + <<: + - *nautobot-base + - *nautobot-build + worker: entrypoint: - "sh" - "-c" # this is to evaluate the $NAUTOBOT_LOG_LEVEL from the env - - "watchmedo auto-restart --directory './' --pattern '*.py' --recursive -- nautobot-server celery worker -l $$NAUTOBOT_LOG_LEVEL --events" + - "nautobot-server celery worker -l $$NAUTOBOT_LOG_LEVEL --events" ## $$ because of docker-compose depends_on: - "nautobot" - - "redis" healthcheck: interval: "30s" timeout: "10s" start_period: "30s" retries: 3 - test: - [ - "CMD", - "bash", - "-c", - "nautobot-server celery inspect ping --destination celery@$$HOSTNAME" - ] + test: ["CMD", "bash", "-c", "nautobot-server celery inspect ping --destination celery@$$HOSTNAME"] ## $$ because of docker-compose <<: *nautobot-base - celery_beat: + beat: entrypoint: - "sh" - - "-c" - - "nautobot-server celery beat -l $$NAUTOBOT_LOG_LEVEL" # this is to evaluate the $NAUTOBOT_LOG_LEVEL from the env - healthcheck: - disable: true + - "-c" # this is to evaluate the $NAUTOBOT_LOG_LEVEL from the env + - "nautobot-server celery beat -l $$NAUTOBOT_LOG_LEVEL" ## $$ because of docker-compose depends_on: - "nautobot" - - "redis" + healthcheck: + disable: true <<: *nautobot-base diff --git a/development/docker-compose.dev.yml b/development/docker-compose.dev.yml index 7bc0b08c..a72667b4 100644 --- a/development/docker-compose.dev.yml +++ b/development/docker-compose.dev.yml @@ -3,23 +3,17 @@ # any override will need to include these volumes to use them. # see: https://github.com/docker/compose/issues/3729 --- -version: "3.4" +version: "3.8" services: nautobot: - command: "nautobot-server runserver 0.0.0.0:8080 --nothreading --insecure" + command: "nautobot-server runserver 0.0.0.0:8080" + ports: + - "8080:8080" volumes: - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - "../:/source" healthcheck: - disable: true - celery_worker: - volumes: - - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - - "../:/source" - celery_beat: - volumes: - - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" - - "../:/source" + test: ["CMD", "true"] # Due to layering, disable: true won't work. Instead, change the test docs: entrypoint: "mkdocs serve -v -a 0.0.0.0:8080" ports: @@ -30,3 +24,20 @@ services: healthcheck: disable: true tty: true + worker: + entrypoint: + - "sh" + - "-c" # this is to evaluate the $NAUTOBOT_LOG_LEVEL from the env + - "watchmedo auto-restart --directory './' --pattern '*.py' --recursive -- nautobot-server celery worker -l $$NAUTOBOT_LOG_LEVEL --events" ## $$ because of docker-compose + volumes: + - "./nautobot_config.py:/opt/nautobot/nautobot_config.py" + - "../:/source" + healthcheck: + test: ["CMD", "true"] # Due to layering, disable: true won't work. Instead, change the test +# To expose postgres or redis to the host uncomment the following +# postgres: +# ports: +# - "5432:5432" +# redis: +# ports: +# - "6379:6379" diff --git a/development/docker-compose.mysql.yml b/development/docker-compose.mysql.yml index 89c51f7d..062ada94 100644 --- a/development/docker-compose.mysql.yml +++ b/development/docker-compose.mysql.yml @@ -1,21 +1,40 @@ --- -version: "3.4" +version: "3.8" services: + nautobot: + environment: + - "NAUTOBOT_DB_ENGINE=django.db.backends.mysql" + env_file: + - "development.env" + - "creds.env" + - "development_mysql.env" + worker: + environment: + - "NAUTOBOT_DB_ENGINE=django.db.backends.mysql" + env_file: + - "development.env" + - "creds.env" + - "development_mysql.env" db: image: "mysql:8" command: - "--default-authentication-plugin=mysql_native_password" + - "--max_connections=1000" env_file: - - "dev.env" + - "development.env" - "creds.env" + - "development_mysql.env" volumes: - - "lcm_mysql_data:/var/lib/mysql" - ports: - - "3306:3306" + - "mysql_data:/var/lib/mysql" healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + test: + - "CMD" + - "mysqladmin" + - "ping" + - "-h" + - "localhost" timeout: "20s" retries: 10 volumes: - lcm_mysql_data: # yamllint disable-line rule:empty-values + mysql_data: {} diff --git a/development/docker-compose.postgres.yml b/development/docker-compose.postgres.yml index 14d58fbb..12d1de31 100644 --- a/development/docker-compose.postgres.yml +++ b/development/docker-compose.postgres.yml @@ -1,18 +1,22 @@ --- -version: "3.4" +version: "3.8" services: + nautobot: + environment: + - "NAUTOBOT_DB_ENGINE=django.db.backends.postgresql" db: image: "postgres:13-alpine" + command: + - "-c" + - "max_connections=200" env_file: - - "dev.env" + - "development.env" - "creds.env" volumes: - "postgres_data:/var/lib/postgresql/data" - ports: - - "127.0.0.1:5432:5432" healthcheck: - test: ["CMD-SHELL", "pg_isready"] + test: "pg_isready --username=$$POSTGRES_USER --dbname=$$POSTGRES_DB" interval: "10s" timeout: "5s" retries: 10 diff --git a/development/docker-compose.redis.yml b/development/docker-compose.redis.yml index e46be29c..6da9fa01 100644 --- a/development/docker-compose.redis.yml +++ b/development/docker-compose.redis.yml @@ -1,14 +1,12 @@ --- -version: "3.4" +version: "3.8" services: 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" + - "-c" # this is to evaluate the $NAUTOBOT_REDIS_PASSWORD from the env + - "redis-server --appendonly yes --requirepass $$NAUTOBOT_REDIS_PASSWORD" env_file: - - "dev.env" + - "development.env" - "creds.env" - ports: - - "6379:6379" diff --git a/development/nautobot_config.py b/development/nautobot_config.py index d9d3b129..bf94c91f 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -1,48 +1,56 @@ -######################### -# # -# Required settings # -# # -######################### - +"""Nautobot development configuration file.""" import os import sys -from django.core.exceptions import ImproperlyConfigured -from nautobot.core.settings import * # noqa: F403 +from nautobot.core.settings import * # noqa: F403 # pylint: disable=wildcard-import,unused-wildcard-import from nautobot.core.settings_funcs import is_truthy, parse_redis_connection -# Enforce required configuration parameters -for key in [ - "ALLOWED_HOSTS", - "POSTGRES_DB", - "POSTGRES_USER", - "POSTGRES_HOST", - "POSTGRES_PASSWORD", - "REDIS_HOST", - "REDIS_PASSWORD", - "SECRET_KEY", -]: - if not os.environ.get(key): - raise ImproperlyConfigured(f"Required environment variable {key} is missing.") +# +# Debug +# + +DEBUG = is_truthy(os.getenv("NAUTOBOT_DEBUG", False)) +_TESTING = len(sys.argv) > 1 and sys.argv[1] == "test" + +if DEBUG and not _TESTING: + DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": lambda _request: True} + + if "debug_toolbar" not in INSTALLED_APPS: # noqa: F405 + INSTALLED_APPS.append("debug_toolbar") # noqa: F405 + if "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE: # noqa: F405 + MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware") # noqa: F405 + +# +# Misc. settings +# +ALLOWED_HOSTS = os.getenv("NAUTOBOT_ALLOWED_HOSTS", "").split(" ") +SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "") -# This is a list of valid fully-qualified domain names (FQDNs) for the Nautobot server. Nautobot will not permit write -# access to the server via any other hostnames. The first FQDN in the list will be treated as the preferred name. # -# Example: ALLOWED_HOSTS = ['nautobot.example.com', 'nautobot.internal.local'] -ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS").split(" ") +# Database +# -# PostgreSQL database configuration. See the Django documentation for a complete list of available parameters: -# https://docs.djangoproject.com/en/stable/ref/settings/#databases +nautobot_db_engine = os.getenv("NAUTOBOT_DB_ENGINE", "django.db.backends.postgresql") +default_db_settings = { + "django.db.backends.postgresql": { + "NAUTOBOT_DB_PORT": "5432", + }, + "django.db.backends.mysql": { + "NAUTOBOT_DB_PORT": "3306", + }, +} DATABASES = { "default": { - "NAME": os.getenv("NAUTOBOT_DB_NAME", "nautobot"), - "USER": os.getenv("NAUTOBOT_DB_USER", ""), - "PASSWORD": os.getenv("NAUTOBOT_DB_PASSWORD", ""), - "HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"), - "PORT": os.getenv("NAUTOBOT_DB_PORT", ""), - "CONN_MAX_AGE": int(os.getenv("NAUTOBOT_DB_TIMEOUT", 300)), - "ENGINE": os.getenv("NAUTOBOT_DB_ENGINE", "django.db.backends.postgresql"), + "NAME": os.getenv("NAUTOBOT_DB_NAME", "nautobot"), # Database name + "USER": os.getenv("NAUTOBOT_DB_USER", ""), # Database username + "PASSWORD": os.getenv("NAUTOBOT_DB_PASSWORD", ""), # Database password + "HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"), # Database server + "PORT": os.getenv( + "NAUTOBOT_DB_PORT", default_db_settings[nautobot_db_engine]["NAUTOBOT_DB_PORT"] + ), # Database port, default to postgres + "CONN_MAX_AGE": int(os.getenv("NAUTOBOT_DB_TIMEOUT", 300)), # Database timeout + "ENGINE": nautobot_db_engine, } } @@ -50,11 +58,11 @@ if DATABASES["default"]["ENGINE"] == "django.db.backends.mysql": DATABASES["default"]["OPTIONS"] = {"charset": "utf8mb4"} -# The django-redis cache is used to establish concurrent locks using Redis. The -# django-rq settings will use the same instance/database by default. # -# This "default" server is now used by RQ_QUEUES. -# >> See: nautobot.core.settings.RQ_QUEUES +# Redis +# + +# The django-redis cache is used to establish concurrent locks using Redis. CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", @@ -66,117 +74,22 @@ } } -# RQ_QUEUES is not set here because it just uses the default that gets imported -# up top via `from nautobot.core.settings import *`. - -# REDIS CACHEOPS +# Redis Cacheops CACHEOPS_REDIS = parse_redis_connection(redis_database=1) -# 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. Nautobot will not run without this defined. For more information, see -# https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-SECRET_KEY -SECRET_KEY = os.environ["SECRET_KEY"] - - -######################### -# # -# Optional settings # -# # -######################### - -# Specify one or more name and email address tuples representing Nautobot 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 Nautobot -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", "") - -# Text to include on the login page above the login form. HTML is allowed. -BANNER_LOGIN = os.environ.get("BANNER_LOGIN", "") - -# Maximum number of days to retain logged changes. Set to 0 to retain changes indefinitely. (Default: 90) -CHANGELOG_RETENTION = int(os.environ.get("NAUTOBOT_CHANGELOG_RETENTION", 90)) - -# If True, all origins will be allowed. Other settings restricting allowed origins will be ignored. -# Defaults to False. Setting this to True can be dangerous, as it allows any website to make -# cross-origin requests to yours. Generally you'll want to restrict the list of allowed origins with -# CORS_ALLOWED_ORIGINS or CORS_ALLOWED_ORIGIN_REGEXES. -CORS_ORIGIN_ALLOW_ALL = is_truthy(os.environ.get("CORS_ORIGIN_ALLOW_ALL", False)) - -# A list of origins that are authorized to make cross-site HTTP requests. Defaults to []. -CORS_ALLOWED_ORIGINS = [ - # 'https://hostname.example.com', -] - -# A list of strings representing regexes that match Origins that are authorized to make cross-site -# HTTP requests. Defaults to []. -CORS_ALLOWED_ORIGIN_REGEXES = [ - # r'^(https?://)?(\w+\.)?example\.com$', -] - -# The file path where jobs will be stored. A trailing slash is not needed. Note that the default value of -# this setting is inside the invoking user's home directory. -# JOBS_ROOT = os.path.expanduser('~/.nautobot/jobs') - -# 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 = is_truthy(os.environ.get("NAUTOBOT_DEBUG", False)) - -# 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 = is_truthy(os.environ.get("ENFORCE_GLOBAL_UNIQUE", False)) - -# 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 `.`. Add '*' to this list to exempt all models. -EXEMPT_VIEW_PERMISSIONS = [ - # 'dcim.site', - # 'dcim.region', - # 'ipam.prefix', -] - -# HTTP proxies Nautobot should use when sending outbound HTTP requests (e.g. for webhooks). -# HTTP_PROXIES = { -# 'http': 'http://10.10.1.10:3128', -# 'https': 'http://10.10.1.10:1080', -# } +# +# Celery settings are not defined here because they can be overloaded with +# environment variables. By default they use `CACHES["default"]["LOCATION"]`. +# -# IP addresses recognized as internal to the system. The debugging toolbar will be available only to clients accessing -# Nautobot from an internal IP. -INTERNAL_IPS = ("127.0.0.1", "::1") +# +# Logging +# -# Enable custom logging. Please see the Django documentation for detailed guidance on configuring custom logs: -# https://docs.djangoproject.com/en/stable/topics/logging/ LOG_LEVEL = "DEBUG" if DEBUG else "INFO" -TESTING = len(sys.argv) > 1 and sys.argv[1] == "test" - # Verbose logging during normal development operation, but quiet logging during unit test execution -if not TESTING: +if not _TESTING: LOGGING = { "version": 1, "disable_existing_loggers": False, @@ -211,52 +124,15 @@ }, } -# Setting this to True will display a "maintenance mode" banner at the top of every page. -MAINTENANCE_MODE = False - -# 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("NAUTOBOT_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 within the invoking user's home directory -# MEDIA_ROOT = os.path.expanduser('~/.nautobot/media') - -# 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': 'nautobot', -# 'AWS_S3_REGION_NAME': 'eu-west-1', -# } - -# Expose Prometheus monitoring metrics at the HTTP endpoint '/metrics' -METRICS_ENABLED = os.environ.get("NAUTOBOT_METRICS_ENABLED", False) - -# Credentials that Nautobot will uses to authenticate to devices when connecting via NAPALM. -NAPALM_USERNAME = os.environ.get("NAPALM_USERNAME", "") -NAPALM_PASSWORD = os.environ.get("NAPALM_PASSWORD", "") - -# NAPALM timeout (in seconds). (Default: 30) -NAPALM_TIMEOUT = int(os.environ.get("NAPALM_TIMEOUT", 30)) - -# NAPALM optional arguments (see https://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)) +# +# Apps +# -# Enable installed plugins. Add the name of each plugin to the list. -PLUGINS = [ - "nautobot_device_lifecycle_mgmt", -] +# Enable installed Apps. Add the name of each App to the list. +PLUGINS = ["nautobot_device_lifecycle_mgmt"] -# 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. +# Apps configuration settings. These settings are used by various Apps that the user may have installed. +# Each key in the dictionary is the name of an installed App and its value is a dictionary of settings. PLUGINS_CONFIG = { "nautobot_device_lifecycle_mgmt": { "barchart_bar_width": float(os.environ.get("BARCHART_BAR_WIDTH", 0.1)), @@ -264,71 +140,3 @@ "barchart_height": int(os.environ.get("BARCHART_HEIGHT", 5)), }, } - -# 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 = is_truthy(os.environ.get("PREFER_IPV4", False)) - -# 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 = 22 -RACK_ELEVATION_DEFAULT_UNIT_WIDTH = 220 - -# Remote authentication support -REMOTE_AUTH_ENABLED = False -REMOTE_AUTH_BACKEND = "nautobot.core.authentication.RemoteUserBackend" -REMOTE_AUTH_HEADER = "HTTP_REMOTE_USER" -REMOTE_AUTH_AUTO_CREATE_USER = True -REMOTE_AUTH_DEFAULT_GROUPS = [] -REMOTE_AUTH_DEFAULT_PERMISSIONS = {} - -# This determines how often the GitHub API is called to check the latest release of Nautobot. Must be at least 1 hour. -RELEASE_CHECK_TIMEOUT = 24 * 3600 - -# This repository is used to check whether there is a new release of Nautobot available. Set to None to disable the -# version check or use the URL below to check for release in the official Nautobot repository. -RELEASE_CHECK_URL = None -# RELEASE_CHECK_URL = 'https://api.github.com/repos/nautobot/nautobot/releases' - -# Maximum execution time for background tasks, in seconds. -RQ_DEFAULT_TIMEOUT = 300 - -# 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]) -SESSION_COOKIE_AGE = 1209600 # 2 weeks, in seconds - - -# By default, Nautobot 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 Nautobot runs must have read and write permissions to this path. -SESSION_FILE_PATH = None - -# Always use IPython for shell_plus -SHELL_PLUS = "ipython" - -# Configure SSO, for more information see docs/configuration/authentication/sso.md -SOCIAL_AUTH_ENABLED = False - -# Time zone (default: UTC) -TIME_ZONE = os.environ.get("TIME_ZONE", "UTC") - -# Date/time formatting. See the following link for supported formats: -# https://docs.djangoproject.com/en/stable/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") - -# A list of strings designating all applications that are enabled in this Django installation. Each string should be -# a dotted Python path to an application configuration class (preferred), or a package containing an application. -# https://nautobot.readthedocs.io/en/latest/configuration/optional-settings/#extra-applications -EXTRA_INSTALLED_APPS = os.environ["EXTRA_INSTALLED_APPS"].split(",") if os.environ.get("EXTRA_INSTALLED_APPS") else [] - -# Django Debug Toolbar -if DEBUG: - DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": lambda _request: DEBUG and not TESTING} - if "debug_toolbar" not in INSTALLED_APPS: # noqa: F405 - INSTALLED_APPS.append("debug_toolbar") # noqa: F405 - if "debug_toolbar.middleware.DebugToolbarMiddleware" not in MIDDLEWARE: # noqa: F405 - MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware") # noqa: F405 diff --git a/docs/admin/install.md b/docs/admin/install.md index 944f398b..05f196d1 100644 --- a/docs/admin/install.md +++ b/docs/admin/install.md @@ -1,8 +1,10 @@ # Installing the App in Nautobot +Here you will find detailed instructions on how to **install** and **configure** the App within your Nautobot environment. + ## Prerequisites -- The plugin is compatible with Nautobot 1.1.6 and higher. +- The plugin is compatible with Nautobot 2.0.0 and higher. - Databases supported: PostgreSQL, MySQL !!! note @@ -48,7 +50,7 @@ PLUGINS_CONFIG = { } ``` -Once the Nautobot configuration is updated, run the Post Upgrade command (`nautobot-server post_upgrade`) to run migrations and clear any cache. +Once the Nautobot configuration is updated, run the Post Upgrade command (`nautobot-server post_upgrade`) to run migrations and clear any cache: ```shell nautobot-server post_upgrade @@ -64,16 +66,13 @@ Then restart (if necessary) the Nautobot services which may include: sudo systemctl restart nautobot nautobot-worker nautobot-scheduler ``` -!!! note - If you are on Nautobot >= 1.1.0 and have the RQ worker continuing on, also restart the RQ worker service: `sudo systemctl restart nautobot-rq-worker`. - - ## App Configuration -The plugin behavior can be controlled with the following list of settings. +The plugin behavior can be controlled with the following list of settings: +| Key | Example | Default | Description | +| -------------------- | ------------------------- | ------- | -------------------------------------------------------------------- | +| `expired_field` | `end_of_support` | | The field name representing the expiry date. | +| `barchart_bar_width` | `0.1` | `0.15` | The width of the table bar within the overview report. | +| `barchart_width` | `12` | | The width of the barchart within the overview report. | +| `barchart_height` | `5` | | The height of the barchart within the overview report. | -| Key | Example | Default | Description | -| ------- | ------ | -------- | ------------------------------------- | -| enable_backup | True | True | A boolean to represent whether or not to run backup configurations within the plugin. | -| platform_slug_map | {"cisco_wlc": "cisco_aireos"} | None | A dictionary in which the key is the platform slug and the value is what netutils uses in any "network_os" parameter. | -| per_feature_bar_width | 0.15 | 0.15 | The width of the table bar within the overview report | diff --git a/docs/admin/release_notes/index.md b/docs/admin/release_notes/index.md index 5793227b..12cb5169 100644 --- a/docs/admin/release_notes/index.md +++ b/docs/admin/release_notes/index.md @@ -1,3 +1,3 @@ # Release Notes -All the published release notes can be found via the navigation menu. All patch releases are included in the same minor release (e.g. `v1.1`) document. +All the published release notes can be found via the navigation menu. All patch releases are included in the same minor release (e.g. `v1.2`) document. diff --git a/docs/admin/uninstall.md b/docs/admin/uninstall.md index 12e4e371..3d51e862 100644 --- a/docs/admin/uninstall.md +++ b/docs/admin/uninstall.md @@ -1,14 +1,15 @@ # Uninstall the App from Nautobot -## Uninstall Guide - -Remove any related configuration you added in `nautobot_config.py` from `PLUGINS` & `PLUGINS_CONFIG`. +Here you will find any steps necessary to cleanly remove the App from your Nautobot environment. ## Database Cleanup -!!! warning "Note - Remove related dependencies prior to dropping database" - Prior to removing this plugin, ensure any related custom fields, relationships, or other dependencies should be removed from the app. +Prior to removing the plugin from the `nautobot_config.py`, run the following command to roll back any migration specific to this plugin. + +```shell +nautobot-server migrate nautobot_plugin_device_lifecycle_mgmt zero +``` -Drop all tables from the plugin: `nautobot_plugin_device_lifecycle_mgmt*`. +## Remove App configuration -Any cleanup operations to ensure the database is clean after the app is removed. +Remove the configuration you added in `nautobot_config.py` from `PLUGINS` & `PLUGINS_CONFIG`. diff --git a/docs/admin/upgrade.md b/docs/admin/upgrade.md index 9d2430a0..c6f4f406 100644 --- a/docs/admin/upgrade.md +++ b/docs/admin/upgrade.md @@ -1,8 +1,10 @@ # Upgrading the App +Here you will find any steps necessary to upgrade the App in your Nautobot environment. + ## Upgrade Guide -This document is intended to provide an upgrade procedure for the Device Lifecycle Plugin within Nautobot. The most stable version of the plugin is available as a Python package in [PyPI](https://pypi.org/project/nautobot-device-lifecycle-mgmt/) and can be upgraded using pip. +When a new release comes out it may be necessary to run a migration of the database to account for any changes in the data models used by this plugin. Execute the command `nautobot-server post-upgrade` within the runtime environment of your Nautobot installation after updating the `nautobot-device-lifecycle-mgmt` package via `pip`. ```shell pip3 install --upgrade nautobot-device-lifecycle-mgmt diff --git a/docs/assets/extra.css b/docs/assets/extra.css index 50884f4a..dfe2e4b1 100644 --- a/docs/assets/extra.css +++ b/docs/assets/extra.css @@ -18,6 +18,15 @@ font-size: 0.7rem; } +/* +* The default max-width is 61rem which does not provide nearly enough space to present code examples or larger tables +*/ +.md-grid { + margin-left: auto; + margin-right: auto; + max-width: 95%; +} + .md-tabs__link { font-size: 0.8rem; } @@ -39,7 +48,7 @@ } img.logo { - height: 100px; + height: 200px; } img.copyright-logo { diff --git a/docs/assets/overrides/partials/copyright.html b/docs/assets/overrides/partials/copyright.html index e0b77e5f..b92cf5e3 100644 --- a/docs/assets/overrides/partials/copyright.html +++ b/docs/assets/overrides/partials/copyright.html @@ -1,3 +1,4 @@ +