From e5c7a0950aa732c343747c4a57bcced7aa421d19 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Sat, 6 Jan 2024 09:38:56 -0500 Subject: [PATCH 01/17] Renaming work (#691) * initial renaming commit * fix test for v2.0 & v2.1 --------- Co-authored-by: Ken Celenza --- .cookiecutter.json | 11 +-- .../pull_request_template.md | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/upstream_testing.yml | 2 +- README.md | 22 ++--- development/nautobot_config.py | 6 +- docs/admin/compatibility_matrix.md | 2 +- docs/admin/install.md | 22 ++--- docs/admin/release_notes/version_0.10.md | 2 +- docs/admin/release_notes/version_0.9.md | 72 ++++++++--------- docs/admin/release_notes/version_1.0.md | 58 +++++++------- docs/admin/release_notes/version_1.1.md | 16 ++-- docs/admin/release_notes/version_1.2.md | 80 +++++++++---------- docs/admin/release_notes/version_1.3.md | 14 ++-- docs/admin/release_notes/version_1.4.md | 66 +++++++-------- docs/admin/release_notes/version_1.5.md | 18 ++--- docs/admin/release_notes/version_1.6.md | 34 ++++---- docs/admin/release_notes/version_2.0.md | 66 +++++++-------- docs/admin/troubleshooting/index.md | 2 +- docs/admin/uninstall.md | 2 +- docs/admin/upgrade.md | 4 +- docs/dev/contributing.md | 2 +- docs/dev/dev_environment.md | 22 ++--- docs/user/app_feature_backup.md | 4 +- docs/user/app_feature_compliance.md | 4 +- docs/user/app_feature_compliancecustom.md | 6 +- docs/user/app_feature_intended.md | 12 +-- docs/user/app_feature_remediation.md | 2 +- docs/user/app_feature_sotagg.md | 6 +- docs/user/app_getting_started.md | 18 ++--- docs/user/app_overview.md | 2 +- docs/user/app_use_cases.md | 24 +++--- docs/user/faq.md | 10 +-- .../troubleshooting/troubleshoot_general.md | 2 +- mkdocs.yml | 4 +- nautobot_golden_config/__init__.py | 4 +- nautobot_golden_config/api/__init__.py | 2 +- nautobot_golden_config/api/serializers.py | 2 +- nautobot_golden_config/datasources.py | 2 +- nautobot_golden_config/forms.py | 2 +- nautobot_golden_config/jobs.py | 2 +- nautobot_golden_config/metrics.py | 2 +- nautobot_golden_config/models.py | 6 +- nautobot_golden_config/navigation.py | 2 +- .../nornir_plays/config_deployment.py | 2 +- .../nornir_plays/config_intended.py | 2 +- nautobot_golden_config/tables.py | 2 +- nautobot_golden_config/template_content.py | 8 +- nautobot_golden_config/tests/__init__.py | 2 +- nautobot_golden_config/tests/test_graphql.py | 4 +- nautobot_golden_config/tests/test_models.py | 2 +- nautobot_golden_config/tests/test_views.py | 9 ++- nautobot_golden_config/urls.py | 2 +- .../utilities/config_postprocessing.py | 6 +- nautobot_golden_config/views.py | 4 +- pyproject.toml | 8 +- tasks.py | 2 +- 57 files changed, 349 insertions(+), 349 deletions(-) diff --git a/.cookiecutter.json b/.cookiecutter.json index d8d0ee46..a18290bd 100644 --- a/.cookiecutter.json +++ b/.cookiecutter.json @@ -4,16 +4,16 @@ "full_name": "Network to Code, LLC", "email": "opensource@networktocode.com", "github_org": "nautobot", - "plugin_name": "nautobot_golden_config", + "app_name": "nautobot_golden_config", "verbose_name": "Golden Config", - "plugin_slug": "nautobot-golden-config", - "project_slug": "nautobot-plugin-golden-config", - "repo_url": "https://github.com/nautobot/nautobot-plugin-golden-config", + "app_slug": "nautobot-golden-config", + "project_slug": "nautobot-app-golden-config", + "repo_url": "https://github.com/nautobot/nautobot-app-golden-config", "base_url": "golden-config", "min_nautobot_version": "2.0.0", "max_nautobot_version": "2.9999", "camel_name": "NautobotGoldenConfig", - "project_short_description": "A plugin for configuration on nautobot", + "project_short_description": "An app for configuration on nautobot", "model_class_name": "None", "open_source_license": "Apache-2.0", "docs_base_url": "https://docs.nautobot.com", @@ -33,3 +33,4 @@ } } } + diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 784d0aba..8d0d0b23 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -30,5 +30,5 @@ - [ ] Attached Screenshots, Payload Example - [ ] Unit, Integration Tests - [ ] Documentation Updates (when adding/changing features) -- [ ] Example Plugin Updates (when adding/changing features) +- [ ] Example App Updates (when adding/changing features) - [ ] Outline Remaining Work, Constraints from Design diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68e3d45e..f6a29728 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ on: # yamllint disable-line rule:truthy rule:comments pull_request: ~ env: - PLUGIN_NAME: "nautobot-plugin-golden-config" + PLUGIN_NAME: "nautobot-app-golden-config" jobs: black: diff --git a/.github/workflows/upstream_testing.yml b/.github/workflows/upstream_testing.yml index 0deb8033..cd8107bd 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_GOLDEN_CONFIG" - plugin_name: "nautobot-plugin-golden-config" + plugin_name: "nautobot-app-golden-config" diff --git a/README.md b/README.md index 26df01cb..3c74b687 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Nautobot Golden Config

- +
- + @@ -13,14 +13,14 @@ ## Overview -The Golden Config plugin is a Nautobot plugin that provides a NetDevOps approach to golden configuration and configuration compliance. +The Golden Config App is a Nautobot App that provides a NetDevOps approach to golden configuration and configuration compliance. !!! info Upgrading to Nautobot and Nautobot Golden Config 2.0, see our [migration guide](https://docs.nautobot.com/projects/golden-config/en/latest/admin/migrating_to_v2/)! ### Key Use Cases -This plugin enable six (6) key use cases. +This app enable six (6) key use cases. 1. **Configuration Backups** - Is a Nornir process to connect to devices, optionally parse out lines/secrets, backup the configuration, and save to a Git repository. 2. **Intended Configuration** - Is a Nornir process to generate configuration based on a Git repo of Jinja files to combine with a GraphQL generated data and a Git repo to store the intended configuration. @@ -35,22 +35,22 @@ This plugin enable six (6) key use cases. ## Screenshots -There are many features and capabilities the plugin provides into the Nautobot ecosystem. The following screenshots are intended to provide a quick visual overview of some of these features. +There are many features and capabilities the app provides into the Nautobot ecosystem. The following screenshots are intended to provide a quick visual overview of some of these features. The golden configuration is driven by jobs that run a series of tasks and the result is captured in this overview. -![Overview](https://raw.githubusercontent.com/nautobot/nautobot-plugin-golden-config/develop/docs/images/ss_golden-overview.png) +![Overview](https://raw.githubusercontent.com/nautobot/nautobot-app-golden-config/develop/docs/images/ss_golden-overview.png) The compliance report provides a high-level overview on the compliance of your network. -![Compliance Report](https://raw.githubusercontent.com/nautobot/nautobot-plugin-golden-config/develop/docs/images/ss_compliance-report.png) +![Compliance Report](https://raw.githubusercontent.com/nautobot/nautobot-app-golden-config/develop/docs/images/ss_compliance-report.png) The compliance overview will provide a per device and feature overview on the compliance of your network devices. -![Compliance Overview](https://raw.githubusercontent.com/nautobot/nautobot-plugin-golden-config/develop/docs/images/ss_compliance-overview.png) +![Compliance Overview](https://raw.githubusercontent.com/nautobot/nautobot-app-golden-config/develop/docs/images/ss_compliance-overview.png) Drilling into a specific device and feature, you can get an immediate detailed understanding of your device. -![Compliance Device](https://raw.githubusercontent.com/nautobot/nautobot-plugin-golden-config/develop/docs/images/ss_compliance-device.png) +![Compliance Device](https://raw.githubusercontent.com/nautobot/nautobot-app-golden-config/develop/docs/images/ss_compliance-device.png) -![Compliance Rule](https://raw.githubusercontent.com/nautobot/nautobot-plugin-golden-config/develop/docs/images/ss_compliance-rule.png) +![Compliance Rule](https://raw.githubusercontent.com/nautobot/nautobot-app-golden-config/develop/docs/images/ss_compliance-rule.png) ## Try it out! @@ -70,7 +70,7 @@ Full web-based HTML documentation for this app can be found over on the [Nautobo ### Contributing to the Docs -You can find all the Markdown source for the App documentation under the [docs](https://github.com/nautobot/nautobot-plugin-golden-config/tree/develop/docs) folder in this repository. For simple edits, a Markdown capable editor is sufficient - clone the repository and edit away. +You can find all the Markdown source for the App documentation under the [docs](https://github.com/nautobot/nautobot-app-golden-config/tree/develop/docs) folder in this repository. For simple edits, a Markdown capable editor is sufficient - clone the repository and edit away. If you need to view the fully generated documentation site, you can build it with [mkdocs](https://www.mkdocs.org/). A container hosting the docs will be started using the invoke commands (details in the [Development Environment Guide](https://docs.nautobot.com/projects/golden-config/en/latest/dev/dev_environment/#docker-development-environment)) on [http://localhost:8001](http://localhost:8001). As your changes are saved, the live docs will be automatically reloaded. diff --git a/development/nautobot_config.py b/development/nautobot_config.py index bd962a65..afdf3fb3 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -128,11 +128,11 @@ # Apps # -# Enable installed plugins. Add the name of each plugin to the list. +# Enable installed apps. Add the name of each app to the list. PLUGINS = ["nautobot_plugin_nornir", "nautobot_golden_config"] -# 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_plugin_nornir": { "nornir_settings": { diff --git a/docs/admin/compatibility_matrix.md b/docs/admin/compatibility_matrix.md index e24d35fd..1a3143c8 100644 --- a/docs/admin/compatibility_matrix.md +++ b/docs/admin/compatibility_matrix.md @@ -4,7 +4,7 @@ Changes to the support of upstream Nautobot releases will be announced 1 minor o The **deprecation policy** will be announced within the [release notes](./release_notes/index.md), and updated in the table below. There will be a `stable-.` branch that will be minimally maintained. Any security enhancements or major bugs in that branch will be supported for a limited time. -While that last supported version will not be strictly enforced via the `max_version` setting, any issues with an updated Nautobot supported version in a minor release will require raising a bug and fixing it in Nautobot core, with no fixes expected in this plugin. This allows the Golden Config plugin the ability to quickly take advantage of the latest features in Nautobot. +While that last supported version will not be strictly enforced via the `max_version` setting, any issues with an updated Nautobot supported version in a minor release will require raising a bug and fixing it in Nautobot core, with no fixes expected in this app. This allows the Golden Config App the ability to quickly take advantage of the latest features in Nautobot. | Golden Config Version | Nautobot First Support Version | Nautobot Last Support Version | | --------------------- | ------------------------------ | ----------------------------- | diff --git a/docs/admin/install.md b/docs/admin/install.md index 0e9f4bf0..ca1dec70 100644 --- a/docs/admin/install.md +++ b/docs/admin/install.md @@ -4,20 +4,20 @@ Here you will find detailed instructions on how to **install** and **configure** ## Prerequisites -- The plugin relies on [`nautobot_plugin_nornir`](https://pypi.org/project/nautobot-plugin-nornir/) to be installed and both plugins to be enabled in your configuration settings. -- The latest version of this plugin is compatible with Nautobot 2.0.0 and higher, see [this dedicated page](compatibility_matrix.md) for a full compatibility matrix and the deprecation policy. +- The app relies on [`nautobot_plugin_nornir`](https://pypi.org/project/nautobot-plugin-nornir/) to be installed and both apps to be enabled in your configuration settings. +- The latest version of this app is compatible with Nautobot 2.0.0 and higher, see [this dedicated page](compatibility_matrix.md) for a full compatibility matrix and the deprecation policy. - Databases supported: PostgreSQL, MySQL ### Access Requirements -There are no access requirements from external systems to this plugin. +There are no access requirements from external systems to this app. ## Install Guide !!! note - Plugins can be installed manually or using Python's `pip`. See the [nautobot documentation](https://nautobot.readthedocs.io/en/latest/plugins/#install-the-package) for more details. The pip package name for this plugin is [`nautobot-golden-config`](https://pypi.org/project/nautobot-golden-config/). + Apps can be installed manually or using Python's `pip`. See the [nautobot documentation](https://nautobot.readthedocs.io/en/latest/plugins/#install-the-package) for more details. The pip package name for this app is [`nautobot-golden-config`](https://pypi.org/project/nautobot-golden-config/). -The plugin is available as a Python package via PyPI and can be installed with `pip`: +The app is available as a Python package via PyPI and can be installed with `pip`: ```shell pip install nautobot-golden-config @@ -29,7 +29,7 @@ To ensure Nautobot Golden Config is automatically re-installed during future upg echo nautobot-golden-config >> local_requirements.txt ``` -Once installed, the plugin needs to be enabled in your Nautobot configuration. The following block of code below shows the additional configuration required to be added to your `nautobot_config.py` file: +Once installed, the app needs to be enabled in your Nautobot configuration. The following block of code below shows the additional configuration required to be added to your `nautobot_config.py` file: - Append `"nautobot_golden_config"` to the `PLUGINS` list, and `"nautobot_plugin_nornir"` if it was not already there (more info [here](https://docs.nautobot.com/projects/plugin-nornir/en/latest/)). - Append the `"nautobot_golden_config"` dictionary to the `PLUGINS_CONFIG` dictionary, and `"nautobot_plugin_nornir"` if it was not already there. @@ -92,17 +92,17 @@ sudo systemctl restart nautobot nautobot-worker nautobot-scheduler ## App Configuration -The plugin behavior can be controlled with the following list of settings: +The app behavior can be controlled with the following list of settings: !!! note The `enable_backup`, `enable_compliance`, `enable_intended`, `enable_sotagg`, `enable_plan`, `enable_deploy`, and `enable_postprocessing` will toggle inclusion of the entire component. | Key | Example | Default | Description | | ------------------------- | ----------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| enable_backup | True | True | A boolean to represent whether or not to run backup configurations within the plugin. | -| enable_compliance | True | True | A boolean to represent whether or not to run the compliance process within the plugin. | -| enable_intended | True | True | A boolean to represent whether or not to generate intended configurations within the plugin. | -| enable_sotagg | True | True | A boolean to represent whether or not to provide a GraphQL query per device to allow the intended configuration to provide data variables to the plugin. | +| enable_backup | True | True | A boolean to represent whether or not to run backup configurations within the app. | +| enable_compliance | True | True | A boolean to represent whether or not to run the compliance process within the app. | +| enable_intended | True | True | A boolean to represent whether or not to generate intended configurations within the app. | +| enable_sotagg | True | True | A boolean to represent whether or not to provide a GraphQL query per device to allow the intended configuration to provide data variables to the app. | | enable_plan | True | True | A boolean to represent whether or not to allow the config plan job to run. | | enable_deploy | True | True | A boolean to represent whether or not to be able to deploy configs to network devices. | | enable_postprocessing | True | False | A boolean to represent whether or not to generate intended configurations to push, with extra processing such as secrets rendering. | diff --git a/docs/admin/release_notes/version_0.10.md b/docs/admin/release_notes/version_0.10.md index bea2c5c4..4628275f 100644 --- a/docs/admin/release_notes/version_0.10.md +++ b/docs/admin/release_notes/version_0.10.md @@ -6,5 +6,5 @@ ### Added -- [#163](https://github.com/nautobot/nautobot-plugin-golden-config/issues/163) Create custom compliance feature +- [#163](https://github.com/nautobot/nautobot-app-golden-config/issues/163) Create custom compliance feature diff --git a/docs/admin/release_notes/version_0.9.md b/docs/admin/release_notes/version_0.9.md index e324267c..36470912 100644 --- a/docs/admin/release_notes/version_0.9.md +++ b/docs/admin/release_notes/version_0.9.md @@ -13,90 +13,90 @@ ### Added -- [#155](https://github.com/nautobot/nautobot-plugin-golden-config/issues/155) Contribution policy updated in Readme +- [#155](https://github.com/nautobot/nautobot-app-golden-config/issues/155) Contribution policy updated in Readme ### Fixed -- [#129](https://github.com/nautobot/nautobot-plugin-golden-config/issues/129) Update filters, forms, add filters to api. -- [#148](https://github.com/nautobot/nautobot-plugin-golden-config/issues/148) move diff2html to be locally served -- [#154](https://github.com/nautobot/nautobot-plugin-golden-config/issues/154) Fix report bar chart overlap -- [#161](https://github.com/nautobot/nautobot-plugin-golden-config/issues/161) Fix configuration compliance export gives traceback -- [#164](https://github.com/nautobot/nautobot-plugin-golden-config/issues/164) Fixes the export functionality for configuration compliance list view. -- [#166](https://github.com/nautobot/nautobot-plugin-golden-config/issues/166) fix configuration and overview reporting csv exports +- [#129](https://github.com/nautobot/nautobot-app-golden-config/issues/129) Update filters, forms, add filters to api. +- [#148](https://github.com/nautobot/nautobot-app-golden-config/issues/148) move diff2html to be locally served +- [#154](https://github.com/nautobot/nautobot-app-golden-config/issues/154) Fix report bar chart overlap +- [#161](https://github.com/nautobot/nautobot-app-golden-config/issues/161) Fix configuration compliance export gives traceback +- [#164](https://github.com/nautobot/nautobot-app-golden-config/issues/164) Fixes the export functionality for configuration compliance list view. +- [#166](https://github.com/nautobot/nautobot-app-golden-config/issues/166) fix configuration and overview reporting csv exports ## v0.9.9 - 2021-10 ### Fixed -- [#146](https://github.com/nautobot/nautobot-plugin-golden-config/issues/146) Removed custom fields from showing in Configuration Overview ListView. -- [#145](https://github.com/nautobot/nautobot-plugin-golden-config/issues/145) Rename all Filterset to be compliant with Nautobot naming convention. -- [#143](https://github.com/nautobot/nautobot-plugin-golden-config/issues/143) Added appropriate metadata tag to jobs. +- [#146](https://github.com/nautobot/nautobot-app-golden-config/issues/146) Removed custom fields from showing in Configuration Overview ListView. +- [#145](https://github.com/nautobot/nautobot-app-golden-config/issues/145) Rename all Filterset to be compliant with Nautobot naming convention. +- [#143](https://github.com/nautobot/nautobot-app-golden-config/issues/143) Added appropriate metadata tag to jobs. ## v0.9.8 - 2021-10 ### Fixed -- [#139](https://github.com/nautobot/nautobot-plugin-golden-config/issues/139) Fixing missing and extra fields, for edge cases. -- [#134](https://github.com/nautobot/nautobot-plugin-golden-config/issues/134) Replace enable_golden with enable_intended in default settings. +- [#139](https://github.com/nautobot/nautobot-app-golden-config/issues/139) Fixing missing and extra fields, for edge cases. +- [#134](https://github.com/nautobot/nautobot-app-golden-config/issues/134) Replace enable_golden with enable_intended in default settings. ## v0.9.7 - 2021-09 ### Fixed -- [#130](https://github.com/nautobot/nautobot-plugin-golden-config/issues/130) SSH Sessions does not die with celery workers, by adding context manager [#128](https://github.com/nautobot/nautobot-plugin-golden-config/pull/128) -- [#125](https://github.com/nautobot/nautobot-plugin-golden-config/issues/125) Update search filterset +- [#130](https://github.com/nautobot/nautobot-app-golden-config/issues/130) SSH Sessions does not die with celery workers, by adding context manager [#128](https://github.com/nautobot/nautobot-app-golden-config/pull/128) +- [#125](https://github.com/nautobot/nautobot-app-golden-config/issues/125) Update search filterset ### Added -- [#126](https://github.com/nautobot/nautobot-plugin-golden-config/issues/126) Add more robust checking for platform -- [#115](https://github.com/nautobot/nautobot-plugin-golden-config/issues/115) Update docs to be more clear on how to use config context +- [#126](https://github.com/nautobot/nautobot-app-golden-config/issues/126) Add more robust checking for platform +- [#115](https://github.com/nautobot/nautobot-app-golden-config/issues/115) Update docs to be more clear on how to use config context ## v0.9.6 - 2021-09 ### Fixed -- [#95](https://github.com/nautobot/nautobot-plugin-golden-config/issues/95) Fix credential escaping issues on Git -- [#113](https://github.com/nautobot/nautobot-plugin-golden-config/issues/113) Clean up and normalize GraphQL decorator -- [#41](https://github.com/nautobot/nautobot-plugin-golden-config/issues/41) Fail Gracefully when platform is missing or wrong, bump nautobot-plugin-nornir version -- [#104](https://github.com/nautobot/nautobot-plugin-golden-config/issues/104) Fail Gracefully when Device queryset is empty -- [#109](https://github.com/nautobot/nautobot-plugin-golden-config/issues/109) Account for Nautobot 1.0/1.1 template change +- [#95](https://github.com/nautobot/nautobot-app-golden-config/issues/95) Fix credential escaping issues on Git +- [#113](https://github.com/nautobot/nautobot-app-golden-config/issues/113) Clean up and normalize GraphQL decorator +- [#41](https://github.com/nautobot/nautobot-app-golden-config/issues/41) Fail Gracefully when platform is missing or wrong, bump nautobot-plugin-nornir version +- [#104](https://github.com/nautobot/nautobot-app-golden-config/issues/104) Fail Gracefully when Device queryset is empty +- [#109](https://github.com/nautobot/nautobot-app-golden-config/issues/109) Account for Nautobot 1.0/1.1 template change ### Added -- [#103](https://github.com/nautobot/nautobot-plugin-golden-config/issues/103) Add manage commands for jobs -- [#108](https://github.com/nautobot/nautobot-plugin-golden-config/issues/108) Update docs and add quick start guide -- [#105](https://github.com/nautobot/nautobot-plugin-golden-config/issues/105) Added structure data config compliance -- [#119](https://github.com/nautobot/nautobot-plugin-golden-config/issues/119) Migrate to Github Actions -- [#121](https://github.com/nautobot/nautobot-plugin-golden-config/issues/121) Moved to Celery for development environment +- [#103](https://github.com/nautobot/nautobot-app-golden-config/issues/103) Add manage commands for jobs +- [#108](https://github.com/nautobot/nautobot-app-golden-config/issues/108) Update docs and add quick start guide +- [#105](https://github.com/nautobot/nautobot-app-golden-config/issues/105) Added structure data config compliance +- [#119](https://github.com/nautobot/nautobot-app-golden-config/issues/119) Migrate to Github Actions +- [#121](https://github.com/nautobot/nautobot-app-golden-config/issues/121) Moved to Celery for development environment - Added Mysql to development environment ## v0.9.5 - 2021-07 ### Fixed -- [#90](https://github.com/nautobot/nautobot-plugin-golden-config/issues/90) Loosen Nautobot version +- [#90](https://github.com/nautobot/nautobot-app-golden-config/issues/90) Loosen Nautobot version ## v0.9.4 - 2021-06 ### Added -- [#87](https://github.com/nautobot/nautobot-plugin-golden-config/issues/87) Added the ability to map arbitrary slug to proper netutils expected network_os +- [#87](https://github.com/nautobot/nautobot-app-golden-config/issues/87) Added the ability to map arbitrary slug to proper netutils expected network_os ### Fixed -- [#87](https://github.com/nautobot/nautobot-plugin-golden-config/issues/87) Dispatcher docs and update dependency for nautobot-plugin-nornir +- [#87](https://github.com/nautobot/nautobot-app-golden-config/issues/87) Dispatcher docs and update dependency for nautobot-plugin-nornir ## v0.9.3 - 2021-06-19 ### Added - - [#81](https://github.com/nautobot/nautobot-plugin-golden-config/issues/85) Added changelog - - [#74](https://github.com/nautobot/nautobot-plugin-golden-config/issues/74) Added hover text to icon on plugin home screen - - [#84](https://github.com/nautobot/nautobot-plugin-golden-config/issues/84) Added auto-deploy to PyPI + - [#81](https://github.com/nautobot/nautobot-app-golden-config/issues/85) Added changelog + - [#74](https://github.com/nautobot/nautobot-app-golden-config/issues/74) Added hover text to icon on app home screen + - [#84](https://github.com/nautobot/nautobot-app-golden-config/issues/84) Added auto-deploy to PyPI ### Fixed -- [#72](https://github.com/nautobot/nautobot-plugin-golden-config/issues/72) Fix uniqueness constraint on update_or_create of config compliance model -- [#75](https://github.com/nautobot/nautobot-plugin-golden-config/issues/75) Updated doc for various images and links -- [#80](https://github.com/nautobot/nautobot-plugin-golden-config/issues/80) Fix navigation when not using compliance -- [#81](https://github.com/nautobot/nautobot-plugin-golden-config/issues/81) Fix settings to set to null instead cascade on delete when removing git repo +- [#72](https://github.com/nautobot/nautobot-app-golden-config/issues/72) Fix uniqueness constraint on update_or_create of config compliance model +- [#75](https://github.com/nautobot/nautobot-app-golden-config/issues/75) Updated doc for various images and links +- [#80](https://github.com/nautobot/nautobot-app-golden-config/issues/80) Fix navigation when not using compliance +- [#81](https://github.com/nautobot/nautobot-app-golden-config/issues/81) Fix settings to set to null instead cascade on delete when removing git repo diff --git a/docs/admin/release_notes/version_1.0.md b/docs/admin/release_notes/version_1.0.md index 136334d5..9a6e802e 100644 --- a/docs/admin/release_notes/version_1.0.md +++ b/docs/admin/release_notes/version_1.0.md @@ -11,54 +11,54 @@ ### Fixed -- [#257](https://github.com/nautobot/nautobot-plugin-golden-config/issues/257) Resolved template_content displaying SoT AGG link on Device detail page if Device not in scope of GoldenConfigSetting +- [#257](https://github.com/nautobot/nautobot-app-golden-config/issues/257) Resolved template_content displaying SoT AGG link on Device detail page if Device not in scope of GoldenConfigSetting - Change to pull version from package instead of static variable ## v1.0.2 - 2022-05 ### Fixed -- [#246](https://github.com/nautobot/nautobot-plugin-golden-config/issues/246) Dependabot update to Docker redis-7.x -- [#233](https://github.com/nautobot/nautobot-plugin-golden-config/issues/233) Dependabot update to paramiko-2.10.1 -- [#251](https://github.com/nautobot/nautobot-plugin-golden-config/issues/251) Add description to CSV config replace export +- [#246](https://github.com/nautobot/nautobot-app-golden-config/issues/246) Dependabot update to Docker redis-7.x +- [#233](https://github.com/nautobot/nautobot-app-golden-config/issues/233) Dependabot update to paramiko-2.10.1 +- [#251](https://github.com/nautobot/nautobot-app-golden-config/issues/251) Add description to CSV config replace export ## v1.0.1 - 2022-05 ### Fixed -- [#238](https://github.com/nautobot/nautobot-plugin-golden-config/issues/238) Fixed repo/docs/homepage links for PyPI -- [#243](https://github.com/nautobot/nautobot-plugin-golden-config/issues/243) Removing unneed javascript source as it is part of [#243](https://github.com/nautobot/nautobot-plugin-golden-config/pull/243) +- [#238](https://github.com/nautobot/nautobot-app-golden-config/issues/238) Fixed repo/docs/homepage links for PyPI +- [#243](https://github.com/nautobot/nautobot-app-golden-config/issues/243) Removing unneed javascript source as it is part of [#243](https://github.com/nautobot/nautobot-app-golden-config/pull/243) ## v1.0.0 - 2022-04 ### Added -- [#180](https://github.com/nautobot/nautobot-plugin-golden-config/issues/180) Added Renovate for proactive package management -- [#158](https://github.com/nautobot/nautobot-plugin-golden-config/issues/158) Allow for Jinja2 Filters to be used by GoldenConfig templates -- [#167](https://github.com/nautobot/nautobot-plugin-golden-config/issues/167) Added support for multiple repos -- [#205](https://github.com/nautobot/nautobot-plugin-golden-config/issues/205) Added support for multiple repos via multiple golden config settings -- [#206](https://github.com/nautobot/nautobot-plugin-golden-config/issues/206) Add Git datasource to load GC properties -- [#218](https://github.com/nautobot/nautobot-plugin-golden-config/issues/218) Added ability to storre SoTAgg field leveraging Nautobot saved GraphQl query -- [#225](https://github.com/nautobot/nautobot-plugin-golden-config/issues/225) Added support for nautobot secrets group on git repos -- [#234](https://github.com/nautobot/nautobot-plugin-golden-config/issues/234) Minor update to FAQ +- [#180](https://github.com/nautobot/nautobot-app-golden-config/issues/180) Added Renovate for proactive package management +- [#158](https://github.com/nautobot/nautobot-app-golden-config/issues/158) Allow for Jinja2 Filters to be used by GoldenConfig templates +- [#167](https://github.com/nautobot/nautobot-app-golden-config/issues/167) Added support for multiple repos +- [#205](https://github.com/nautobot/nautobot-app-golden-config/issues/205) Added support for multiple repos via multiple golden config settings +- [#206](https://github.com/nautobot/nautobot-app-golden-config/issues/206) Add Git datasource to load GC properties +- [#218](https://github.com/nautobot/nautobot-app-golden-config/issues/218) Added ability to storre SoTAgg field leveraging Nautobot saved GraphQl query +- [#225](https://github.com/nautobot/nautobot-app-golden-config/issues/225) Added support for nautobot secrets group on git repos +- [#234](https://github.com/nautobot/nautobot-app-golden-config/issues/234) Minor update to FAQ ### Changed -- [#171](https://github.com/nautobot/nautobot-plugin-golden-config/issues/171) Changed the release policy -- [#158](https://github.com/nautobot/nautobot-plugin-golden-config/issues/158) Changed variable job_result to nautobot_job -- [#186](https://github.com/nautobot/nautobot-plugin-golden-config/issues/186) Update mariadb Docker tag to v10.7 -- [#187](https://github.com/nautobot/nautobot-plugin-golden-config/issues/187) Update postgres Docker tag to v14 -- [#188](https://github.com/nautobot/nautobot-plugin-golden-config/issues/188) Update Markdown dependency -- [#190](https://github.com/nautobot/nautobot-plugin-golden-config/issues/190) Update to Nautobot 1.2.0 -- [#190](https://github.com/nautobot/nautobot-plugin-golden-config/issues/190) Remove Nautobot 1.0 specific code -- [#211](https://github.com/nautobot/nautobot-plugin-golden-config/issues/211) Update dependency mariadb to v10.8 -- [#229](https://github.com/nautobot/nautobot-plugin-golden-config/issues/229) Updated navigation to a dedicated top level menu +- [#171](https://github.com/nautobot/nautobot-app-golden-config/issues/171) Changed the release policy +- [#158](https://github.com/nautobot/nautobot-app-golden-config/issues/158) Changed variable job_result to nautobot_job +- [#186](https://github.com/nautobot/nautobot-app-golden-config/issues/186) Update mariadb Docker tag to v10.7 +- [#187](https://github.com/nautobot/nautobot-app-golden-config/issues/187) Update postgres Docker tag to v14 +- [#188](https://github.com/nautobot/nautobot-app-golden-config/issues/188) Update Markdown dependency +- [#190](https://github.com/nautobot/nautobot-app-golden-config/issues/190) Update to Nautobot 1.2.0 +- [#190](https://github.com/nautobot/nautobot-app-golden-config/issues/190) Remove Nautobot 1.0 specific code +- [#211](https://github.com/nautobot/nautobot-app-golden-config/issues/211) Update dependency mariadb to v10.8 +- [#229](https://github.com/nautobot/nautobot-app-golden-config/issues/229) Updated navigation to a dedicated top level menu ### Fixed -- [#176](https://github.com/nautobot/nautobot-plugin-golden-config/issues/176) Fixed Pylint issue -- [#182](https://github.com/nautobot/nautobot-plugin-golden-config/issues/182) Add reference to Nornir plugin for installation -- [#183](https://github.com/nautobot/nautobot-plugin-golden-config/issues/183) Fixed documentation for sot_agg_transposer default -- [#184](https://github.com/nautobot/nautobot-plugin-golden-config/issues/184) Fix markdown links in quick-start -- [#194](https://github.com/nautobot/nautobot-plugin-golden-config/issues/194) Detailed Error Handling in get_job_filter helper -- [#229](https://github.com/nautobot/nautobot-plugin-golden-config/issues/229) Fixed [#165](https://github.com/nautobot/nautobot-plugin-golden-config/pull/165), Configuration Compliance List View "Device" filter doesn't work +- [#176](https://github.com/nautobot/nautobot-app-golden-config/issues/176) Fixed Pylint issue +- [#182](https://github.com/nautobot/nautobot-app-golden-config/issues/182) Add reference to Nornir app for installation +- [#183](https://github.com/nautobot/nautobot-app-golden-config/issues/183) Fixed documentation for sot_agg_transposer default +- [#184](https://github.com/nautobot/nautobot-app-golden-config/issues/184) Fix markdown links in quick-start +- [#194](https://github.com/nautobot/nautobot-app-golden-config/issues/194) Detailed Error Handling in get_job_filter helper +- [#229](https://github.com/nautobot/nautobot-app-golden-config/issues/229) Fixed [#165](https://github.com/nautobot/nautobot-app-golden-config/pull/165), Configuration Compliance List View "Device" filter doesn't work diff --git a/docs/admin/release_notes/version_1.1.md b/docs/admin/release_notes/version_1.1.md index 667c4a96..a6f84bd9 100644 --- a/docs/admin/release_notes/version_1.1.md +++ b/docs/admin/release_notes/version_1.1.md @@ -11,29 +11,29 @@ ### Fixed -- [#329](https://github.com/nautobot/nautobot-plugin-golden-config/issues/329) Change the pivot to use slug as name could have special characters that cause failures: Cherry picked +- [#329](https://github.com/nautobot/nautobot-app-golden-config/issues/329) Change the pivot to use slug as name could have special characters that cause failures: Cherry picked ## v1.1.2 - 2022-08 ### Changed -- [#322](https://github.com/nautobot/nautobot-plugin-golden-config/issues/322) Create release v1.1.2 and remove restrictions enforcing non-usage of beyond Nautobot 1.3. +- [#322](https://github.com/nautobot/nautobot-app-golden-config/issues/322) Create release v1.1.2 and remove restrictions enforcing non-usage of beyond Nautobot 1.3. ## v1.1.1 - 2022-08 ### Fixed -- [#260](https://github.com/nautobot/nautobot-plugin-golden-config/issues/260) Server Error when viewing Compliance Report : Cherry picked -- [#309](https://github.com/nautobot/nautobot-plugin-golden-config/issues/309) Fix duplicate entries on home view: Cherry picked +- [#260](https://github.com/nautobot/nautobot-app-golden-config/issues/260) Server Error when viewing Compliance Report : Cherry picked +- [#309](https://github.com/nautobot/nautobot-app-golden-config/issues/309) Fix duplicate entries on home view: Cherry picked ## v1.1.0 - 2022-06 ### Fixed -- [#281](https://github.com/nautobot/nautobot-plugin-golden-config/issues/281) Fixes Views for Nautobot 1.3 Settings, backwards compatible with Nautobot 1.2 -- [#270](https://github.com/nautobot/nautobot-plugin-golden-config/issues/270) Optimize GoldenConfig home view to improve scaling with > 1 GoldenConfigSetting via query annotations +- [#281](https://github.com/nautobot/nautobot-app-golden-config/issues/281) Fixes Views for Nautobot 1.3 Settings, backwards compatible with Nautobot 1.2 +- [#270](https://github.com/nautobot/nautobot-app-golden-config/issues/270) Optimize GoldenConfig home view to improve scaling with > 1 GoldenConfigSetting via query annotations ### Added -- [#267](https://github.com/nautobot/nautobot-plugin-golden-config/issues/267) Add filterset to the GoldenConfigSettingViewSet -- [#262](https://github.com/nautobot/nautobot-plugin-golden-config/issues/262) Add filter for slug on ComplianceFeature +- [#267](https://github.com/nautobot/nautobot-app-golden-config/issues/267) Add filterset to the GoldenConfigSettingViewSet +- [#262](https://github.com/nautobot/nautobot-app-golden-config/issues/262) Add filter for slug on ComplianceFeature diff --git a/docs/admin/release_notes/version_1.2.md b/docs/admin/release_notes/version_1.2.md index ca01c20a..c1455c03 100644 --- a/docs/admin/release_notes/version_1.2.md +++ b/docs/admin/release_notes/version_1.2.md @@ -9,88 +9,88 @@ ### Fixed -- [#382](https://github.com/nautobot/nautobot-plugin-golden-config/issues/382) Fixed issue on Golden Config Home Export Inconsistent on filtering. -- [#390](https://github.com/nautobot/nautobot-plugin-golden-config/pull/390) Update ordered compliant view to only show "config" vs both intended and actual. +- [#382](https://github.com/nautobot/nautobot-app-golden-config/issues/382) Fixed issue on Golden Config Home Export Inconsistent on filtering. +- [#390](https://github.com/nautobot/nautobot-app-golden-config/pull/390) Update ordered compliant view to only show "config" vs both intended and actual. ## v1.2.3 - 2022-11 ### Fixed -- [#356](https://github.com/nautobot/nautobot-plugin-golden-config/issues/356) Fix Compliance Rule list view filtering on platform is broken. -- [#385](https://github.com/nautobot/nautobot-plugin-golden-config/pull/385) Fix Compliance Export not working. -- [#384](https://github.com/nautobot/nautobot-plugin-golden-config/pull/384) Fix issue where not correctly rendering intended actual configs on compliance view -- [#387](https://github.com/nautobot/nautobot-plugin-golden-config/pull/387) Fix filter to be in line with Nautobot 1.4, make logging optional in testing. +- [#356](https://github.com/nautobot/nautobot-app-golden-config/issues/356) Fix Compliance Rule list view filtering on platform is broken. +- [#385](https://github.com/nautobot/nautobot-app-golden-config/pull/385) Fix Compliance Export not working. +- [#384](https://github.com/nautobot/nautobot-app-golden-config/pull/384) Fix issue where not correctly rendering intended actual configs on compliance view +- [#387](https://github.com/nautobot/nautobot-app-golden-config/pull/387) Fix filter to be in line with Nautobot 1.4, make logging optional in testing. ## v1.2.2 - 2022-10 ### Fixed -- [#369](https://github.com/nautobot/nautobot-plugin-golden-config/issues/369) Using of runner plugin serial is causing an "InterfaceError: connection already closed" error. +- [#369](https://github.com/nautobot/nautobot-app-golden-config/issues/369) Using of runner app serial is causing an "InterfaceError: connection already closed" error. ### Changed -- [#367](https://github.com/nautobot/nautobot-plugin-golden-config/pull/367) Add suggested custom CSS for mkdocstrings indentation. +- [#367](https://github.com/nautobot/nautobot-app-golden-config/pull/367) Add suggested custom CSS for mkdocstrings indentation. ## v1.2.1 - 2022-10 ### Fixed -- [#350](https://github.com/nautobot/nautobot-plugin-golden-config/pull/350) Fix lingering ssh connections by adding a close_connections in completed stage of processor. -- [#317](https://github.com/nautobot/nautobot-plugin-golden-config/issues/317) Fix The CI builds the Nautobot container two times in the unittests step. -- [#307](https://github.com/nautobot/nautobot-plugin-golden-config/issues/307) Fix `Bulk Delete` not always working on config compliance objects. -- [#358](https://github.com/nautobot/nautobot-plugin-golden-config/pull/358) Fix code block formatting in app_getting_started.md. -- [#352](https://github.com/nautobot/nautobot-plugin-golden-config/pull/352) Fix clearing DB connections between threads. +- [#350](https://github.com/nautobot/nautobot-app-golden-config/pull/350) Fix lingering ssh connections by adding a close_connections in completed stage of processor. +- [#317](https://github.com/nautobot/nautobot-app-golden-config/issues/317) Fix The CI builds the Nautobot container two times in the unittests step. +- [#307](https://github.com/nautobot/nautobot-app-golden-config/issues/307) Fix `Bulk Delete` not always working on config compliance objects. +- [#358](https://github.com/nautobot/nautobot-app-golden-config/pull/358) Fix code block formatting in app_getting_started.md. +- [#352](https://github.com/nautobot/nautobot-app-golden-config/pull/352) Fix clearing DB connections between threads. ### Changed -- [#361](https://github.com/nautobot/nautobot-plugin-golden-config/pull/361) Adds environment variable to disable git prompts. -- [#362](https://github.com/nautobot/nautobot-plugin-golden-config/pull/362) Optimizing refreshing of repos when running jobs. +- [#361](https://github.com/nautobot/nautobot-app-golden-config/pull/361) Adds environment variable to disable git prompts. +- [#362](https://github.com/nautobot/nautobot-app-golden-config/pull/362) Optimizing refreshing of repos when running jobs. ## v1.2.0 - 2022-08 ### Changed -- [#323](https://github.com/nautobot/nautobot-plugin-golden-config/pull/323) Disable enforcement of `max_version` check and update admin install policy to indicate the same. -- [#321](https://github.com/nautobot/nautobot-plugin-golden-config/pull/321) Change source class to align with nautobot v1.4.0. -- [#324](https://github.com/nautobot/nautobot-plugin-golden-config/pull/324) Performance enhancements for dynamic groups. -- [#325](https://github.com/nautobot/nautobot-plugin-golden-config/pull/325) Doc updates. +- [#323](https://github.com/nautobot/nautobot-app-golden-config/pull/323) Disable enforcement of `max_version` check and update admin install policy to indicate the same. +- [#321](https://github.com/nautobot/nautobot-app-golden-config/pull/321) Change source class to align with nautobot v1.4.0. +- [#324](https://github.com/nautobot/nautobot-app-golden-config/pull/324) Performance enhancements for dynamic groups. +- [#325](https://github.com/nautobot/nautobot-app-golden-config/pull/325) Doc updates. ### Fixed -- [#314](https://github.com/nautobot/nautobot-plugin-golden-config/issues/314) Fixed Tag filtering not working in job launch form -- [#316](https://github.com/nautobot/nautobot-plugin-golden-config/pull/316) & [#313](https://github.com/nautobot/nautobot-plugin-golden-config/pull/313) Update doc links for new read the docs -- [#306](https://github.com/nautobot/nautobot-plugin-golden-config/pull/306) Fix ability to run docs locally -- [#304](https://github.com/nautobot/nautobot-plugin-golden-config/pull/304) & [#305](https://github.com/nautobot/nautobot-plugin-golden-config/pull/305) Fix yaml line issues -- [#321](https://github.com/nautobot/nautobot-plugin-golden-config/pull/321) Resolving deprecation warning from upgrading to Nautobot v1.4.0. -- [#324](https://github.com/nautobot/nautobot-plugin-golden-config/pull/324) Provide performance enhancements to querying DynamicGroup members. -- [#328](https://github.com/nautobot/nautobot-plugin-golden-config/pull/328) Update container to be variable rather than hard code to py3.7. -- [#327](https://github.com/nautobot/nautobot-plugin-golden-config/pull/327) Change the pivot to use slug as name could have special characters that cause failures -- [#323](https://github.com/nautobot/nautobot-plugin-golden-config/pull/323) Convert to slug to match view +- [#314](https://github.com/nautobot/nautobot-app-golden-config/issues/314) Fixed Tag filtering not working in job launch form +- [#316](https://github.com/nautobot/nautobot-app-golden-config/pull/316) & [#313](https://github.com/nautobot/nautobot-app-golden-config/pull/313) Update doc links for new read the docs +- [#306](https://github.com/nautobot/nautobot-app-golden-config/pull/306) Fix ability to run docs locally +- [#304](https://github.com/nautobot/nautobot-app-golden-config/pull/304) & [#305](https://github.com/nautobot/nautobot-app-golden-config/pull/305) Fix yaml line issues +- [#321](https://github.com/nautobot/nautobot-app-golden-config/pull/321) Resolving deprecation warning from upgrading to Nautobot v1.4.0. +- [#324](https://github.com/nautobot/nautobot-app-golden-config/pull/324) Provide performance enhancements to querying DynamicGroup members. +- [#328](https://github.com/nautobot/nautobot-app-golden-config/pull/328) Update container to be variable rather than hard code to py3.7. +- [#327](https://github.com/nautobot/nautobot-app-golden-config/pull/327) Change the pivot to use slug as name could have special characters that cause failures +- [#323](https://github.com/nautobot/nautobot-app-golden-config/pull/323) Convert to slug to match view ## v1.2.0b1 - 2022-08 ### Added -- [#291](https://github.com/nautobot/nautobot-plugin-golden-config/pull/291) Updated codeowners +- [#291](https://github.com/nautobot/nautobot-app-golden-config/pull/291) Updated codeowners ### Changed -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) DynamicGroup Support -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) Updated invoke tasks to current standards -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) Initial changes for CI to work with latest pattern -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) GoldenConfigSetting.scope is not a property that maps to GoldenConfigSetting.dynamic_group.filter -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) GoldenConfigSetting.scope now has a setter method to create a DynamicGroup +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) DynamicGroup Support +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) Updated invoke tasks to current standards +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) Initial changes for CI to work with latest pattern +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) GoldenConfigSetting.scope is not a property that maps to GoldenConfigSetting.dynamic_group.filter +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) GoldenConfigSetting.scope now has a setter method to create a DynamicGroup - Scope of Device objects can only be updated via the DynamicGroup is using the UI - The setter is for backwards compantibility for existing automation against the API -- [#280](https://github.com/nautobot/nautobot-plugin-golden-config/issues/280) Updated docs in preparation for doc centralization process -- [#289](https://github.com/nautobot/nautobot-plugin-golden-config/issues/289) Update Environment setup to NTC Standards -- [#287](https://github.com/nautobot/nautobot-plugin-golden-config/issues/287) Updated copy button to use Nautobot's standard copy functionality rather than one off +- [#280](https://github.com/nautobot/nautobot-app-golden-config/issues/280) Updated docs in preparation for doc centralization process +- [#289](https://github.com/nautobot/nautobot-app-golden-config/issues/289) Update Environment setup to NTC Standards +- [#287](https://github.com/nautobot/nautobot-app-golden-config/issues/287) Updated copy button to use Nautobot's standard copy functionality rather than one off ### Fixed -- [#260](https://github.com/nautobot/nautobot-plugin-golden-config/issues/260) Fixed issue with Compliance Report when values were None -- [#299](https://github.com/nautobot/nautobot-plugin-golden-config/issues/299) Updated Readme images to render properly on PyPi, fixed other links +- [#260](https://github.com/nautobot/nautobot-app-golden-config/issues/260) Fixed issue with Compliance Report when values were None +- [#299](https://github.com/nautobot/nautobot-app-golden-config/issues/299) Updated Readme images to render properly on PyPi, fixed other links ### Removed -- [#288](https://github.com/nautobot/nautobot-plugin-golden-config/issues/288) Nautobot <1.4.0 support +- [#288](https://github.com/nautobot/nautobot-app-golden-config/issues/288) Nautobot <1.4.0 support diff --git a/docs/admin/release_notes/version_1.3.md b/docs/admin/release_notes/version_1.3.md index 0396da8f..26f90343 100644 --- a/docs/admin/release_notes/version_1.3.md +++ b/docs/admin/release_notes/version_1.3.md @@ -5,21 +5,21 @@ ## v1.3.1 - 2022-12 -- [#411](https://github.com/nautobot/nautobot-plugin-golden-config/issues/411) - Fix issue where logs were causing an issue. +- [#411](https://github.com/nautobot/nautobot-app-golden-config/issues/411) - Fix issue where logs were causing an issue. ## v1.3.0 - 2022-12 ### Added -- [#344](https://github.com/nautobot/nautobot-plugin-golden-config/issues/344) - Enable routine testing against upstream Nautobot versions to ensure continuous compatibility. -- [#339](https://github.com/nautobot/nautobot-plugin-golden-config/issues/339) - Add the ability to post-process Intended Configuration for multiple use cases, supporting rendering of secrets out of the box. +- [#344](https://github.com/nautobot/nautobot-app-golden-config/issues/344) - Enable routine testing against upstream Nautobot versions to ensure continuous compatibility. +- [#339](https://github.com/nautobot/nautobot-app-golden-config/issues/339) - Add the ability to post-process Intended Configuration for multiple use cases, supporting rendering of secrets out of the box. ### Changed -- [#378](https://github.com/nautobot/nautobot-plugin-golden-config/issues/378) - Update nornir job logging to provide more feedback on the steps that are taking place. -- [#365](https://github.com/nautobot/nautobot-plugin-golden-config/issues/365) - Add slack notify after release to Github Actions workflow. +- [#378](https://github.com/nautobot/nautobot-app-golden-config/issues/378) - Update nornir job logging to provide more feedback on the steps that are taking place. +- [#365](https://github.com/nautobot/nautobot-app-golden-config/issues/365) - Add slack notify after release to Github Actions workflow. ### Fixed -- [#369](https://github.com/nautobot/nautobot-plugin-golden-config/issues/369) - Fix issue with runner serial resulting in `InterfaceError: connection already closed` error. -- [#398](https://github.com/nautobot/nautobot-plugin-golden-config/issues/398) - Fix incorrect relative link in app_feature_compliance.md. +- [#369](https://github.com/nautobot/nautobot-app-golden-config/issues/369) - Fix issue with runner serial resulting in `InterfaceError: connection already closed` error. +- [#398](https://github.com/nautobot/nautobot-app-golden-config/issues/398) - Fix incorrect relative link in app_feature_compliance.md. diff --git a/docs/admin/release_notes/version_1.4.md b/docs/admin/release_notes/version_1.4.md index d03fc888..1c41f83b 100755 --- a/docs/admin/release_notes/version_1.4.md +++ b/docs/admin/release_notes/version_1.4.md @@ -6,55 +6,55 @@ ### Changed -- [#519](https://github.com/nautobot/nautobot-plugin-golden-config/pull/519) - docs-only: large fixes and template troubleshooting section. +- [#519](https://github.com/nautobot/nautobot-app-golden-config/pull/519) - docs-only: large fixes and template troubleshooting section. ### Fixed -- [#492](https://github.com/nautobot/nautobot-plugin-golden-config/pull/492) - Fix count of in scope devices on settings detail view. -- [#498](https://github.com/nautobot/nautobot-plugin-golden-config/pull/498) - Fix deepdiff dependency. -- [#501](https://github.com/nautobot/nautobot-plugin-golden-config/pull/501) - Update docs for adding CustomField data with datasources. -- [#503](https://github.com/nautobot/nautobot-plugin-golden-config/pull/503) - Switch from deprecated FilterSet to new FilterSetMixin. -- [#504](https://github.com/nautobot/nautobot-plugin-golden-config/pull/504) - Fix extend queryfilter to export. -- [#511](https://github.com/nautobot/nautobot-plugin-golden-config/pull/511) - Fix `log_failure` function missing argument. -- [#523](https://github.com/nautobot/nautobot-plugin-golden-config/pull/523) - Fix docs site by pinning dev dependencies. -- [#530](https://github.com/nautobot/nautobot-plugin-golden-config/pull/530) - Fix, removing ConfigCompliance model import from 0005 migration. +- [#492](https://github.com/nautobot/nautobot-app-golden-config/pull/492) - Fix count of in scope devices on settings detail view. +- [#498](https://github.com/nautobot/nautobot-app-golden-config/pull/498) - Fix deepdiff dependency. +- [#501](https://github.com/nautobot/nautobot-app-golden-config/pull/501) - Update docs for adding CustomField data with datasources. +- [#503](https://github.com/nautobot/nautobot-app-golden-config/pull/503) - Switch from deprecated FilterSet to new FilterSetMixin. +- [#504](https://github.com/nautobot/nautobot-app-golden-config/pull/504) - Fix extend queryfilter to export. +- [#511](https://github.com/nautobot/nautobot-app-golden-config/pull/511) - Fix `log_failure` function missing argument. +- [#523](https://github.com/nautobot/nautobot-app-golden-config/pull/523) - Fix docs site by pinning dev dependencies. +- [#530](https://github.com/nautobot/nautobot-app-golden-config/pull/530) - Fix, removing ConfigCompliance model import from 0005 migration. ## v1.4.1 - 2023-05 ### Fixed -- [#488](https://github.com/nautobot/nautobot-plugin-golden-config/pull/488) - Fix Golden Config Settings Buttons. +- [#488](https://github.com/nautobot/nautobot-app-golden-config/pull/488) - Fix Golden Config Settings Buttons. ## v1.4.0 - 2023-05 ### Added -- [#445](https://github.com/nautobot/nautobot-plugin-golden-config/pull/445) - Add validation for Settings sot_agg_query. -- [#449](https://github.com/nautobot/nautobot-plugin-golden-config/pull/449) - Allows for custom kwargs to `get_secret_by_secret_group_slug`. -- [#470](https://github.com/nautobot/nautobot-plugin-golden-config/pull/470) - Enhance UI settings detail object view. -- [#473](https://github.com/nautobot/nautobot-plugin-golden-config/pull/473) - Add status selection field to job filtering. -- [#480](https://github.com/nautobot/nautobot-plugin-golden-config/pull/480) - Add compliance summary to default tenant view. +- [#445](https://github.com/nautobot/nautobot-app-golden-config/pull/445) - Add validation for Settings sot_agg_query. +- [#449](https://github.com/nautobot/nautobot-app-golden-config/pull/449) - Allows for custom kwargs to `get_secret_by_secret_group_slug`. +- [#470](https://github.com/nautobot/nautobot-app-golden-config/pull/470) - Enhance UI settings detail object view. +- [#473](https://github.com/nautobot/nautobot-app-golden-config/pull/473) - Add status selection field to job filtering. +- [#480](https://github.com/nautobot/nautobot-app-golden-config/pull/480) - Add compliance summary to default tenant view. ### Changed -- [#414](https://github.com/nautobot/nautobot-plugin-golden-config/pull/414) - Update application description for UI. -- [#407](https://github.com/nautobot/nautobot-plugin-golden-config/pull/407) - Update branching policy in contributing docs. -- [#417](https://github.com/nautobot/nautobot-plugin-golden-config/pull/417) - Changed extends base.html to extends generic/object_detail.html. -- [#434](https://github.com/nautobot/nautobot-plugin-golden-config/pull/434) - Upgrade deepdiff dependency to 6.2.0. -- [#451](https://github.com/nautobot/nautobot-plugin-golden-config/pull/451) - Tune Dependabot. -- [#459](https://github.com/nautobot/nautobot-plugin-golden-config/pull/459) - Update tasks.py to meet current standards. -- [#464](https://github.com/nautobot/nautobot-plugin-golden-config/pull/464) - Update ordering on compliance views. -- [#471](https://github.com/nautobot/nautobot-plugin-golden-config/pull/471) - Migrate to using NautobotUIViewset and other initial 2.x prep work. -- [#481](https://github.com/nautobot/nautobot-plugin-golden-config/pull/481) - Update filtersets for rack-group to extend proper TreeNode parent. +- [#414](https://github.com/nautobot/nautobot-app-golden-config/pull/414) - Update application description for UI. +- [#407](https://github.com/nautobot/nautobot-app-golden-config/pull/407) - Update branching policy in contributing docs. +- [#417](https://github.com/nautobot/nautobot-app-golden-config/pull/417) - Changed extends base.html to extends generic/object_detail.html. +- [#434](https://github.com/nautobot/nautobot-app-golden-config/pull/434) - Upgrade deepdiff dependency to 6.2.0. +- [#451](https://github.com/nautobot/nautobot-app-golden-config/pull/451) - Tune Dependabot. +- [#459](https://github.com/nautobot/nautobot-app-golden-config/pull/459) - Update tasks.py to meet current standards. +- [#464](https://github.com/nautobot/nautobot-app-golden-config/pull/464) - Update ordering on compliance views. +- [#471](https://github.com/nautobot/nautobot-app-golden-config/pull/471) - Migrate to using NautobotUIViewset and other initial 2.x prep work. +- [#481](https://github.com/nautobot/nautobot-app-golden-config/pull/481) - Update filtersets for rack-group to extend proper TreeNode parent. ### Fixed -- [#436](https://github.com/nautobot/nautobot-plugin-golden-config/pull/436) - Update FAQ for how compliance works. -- [#444](https://github.com/nautobot/nautobot-plugin-golden-config/pull/444) - `app_faq.md` references incorrect `Cisco IOS XR` platform slug. -- [#446](https://github.com/nautobot/nautobot-plugin-golden-config/pull/446) - Fix mysql not working in github actions. -- [#450](https://github.com/nautobot/nautobot-plugin-golden-config/pull/450) - Make ConfigReplace export match import. -- [#456](https://github.com/nautobot/nautobot-plugin-golden-config/pull/456) - Fix postprocessing to use Sandbox Jinja2 environment. -- [#461](https://github.com/nautobot/nautobot-plugin-golden-config/pull/461) - Moves dependabot config to proper location. -- [#463](https://github.com/nautobot/nautobot-plugin-golden-config/pull/463) - Fix Json render in compliance reporting template. -- [#468](https://github.com/nautobot/nautobot-plugin-golden-config/pull/468) - Fix GoldenConfig list view and csv export. -- [#474](https://github.com/nautobot/nautobot-plugin-golden-config/pull/474) - Docs update: Fix multiple typos. +- [#436](https://github.com/nautobot/nautobot-app-golden-config/pull/436) - Update FAQ for how compliance works. +- [#444](https://github.com/nautobot/nautobot-app-golden-config/pull/444) - `app_faq.md` references incorrect `Cisco IOS XR` platform slug. +- [#446](https://github.com/nautobot/nautobot-app-golden-config/pull/446) - Fix mysql not working in github actions. +- [#450](https://github.com/nautobot/nautobot-app-golden-config/pull/450) - Make ConfigReplace export match import. +- [#456](https://github.com/nautobot/nautobot-app-golden-config/pull/456) - Fix postprocessing to use Sandbox Jinja2 environment. +- [#461](https://github.com/nautobot/nautobot-app-golden-config/pull/461) - Moves dependabot config to proper location. +- [#463](https://github.com/nautobot/nautobot-app-golden-config/pull/463) - Fix Json render in compliance reporting template. +- [#468](https://github.com/nautobot/nautobot-app-golden-config/pull/468) - Fix GoldenConfig list view and csv export. +- [#474](https://github.com/nautobot/nautobot-app-golden-config/pull/474) - Docs update: Fix multiple typos. diff --git a/docs/admin/release_notes/version_1.5.md b/docs/admin/release_notes/version_1.5.md index 46e0d40f..b3a68bc3 100755 --- a/docs/admin/release_notes/version_1.5.md +++ b/docs/admin/release_notes/version_1.5.md @@ -2,7 +2,7 @@ - Add ability to update JSON based compliance via a job and have git integrations. - Made custom compliance a boolean to support both JSON or CLI custom compliance types. -- Add metrics for Golden Config plugin. +- Add metrics for Golden Config app. - Add jinja settings support. - Updated Filters for various models, including adding an experimental `_isnull` on DateTime objects. - Supports Nautobot >=1.6.1,<2.0.0. @@ -11,17 +11,17 @@ ### Added -- [#455](https://github.com/nautobot/nautobot-plugin-golden-config/pull/455) - Add metrics for Golden Config plugin. -- [#485](https://github.com/nautobot/nautobot-plugin-golden-config/pull/485) - Custom compliance for CLI and JSON rules. -- [#487](https://github.com/nautobot/nautobot-plugin-golden-config/pull/487) - Implement native JSON support. -- [#527](https://github.com/nautobot/nautobot-plugin-golden-config/pull/527) - Add the ability to update Jinja environment setting from nautobot_config. -- [#558](https://github.com/nautobot/nautobot-plugin-golden-config/pull/558) - Updated Filters for various models, including adding an experimental `_isnull` on DateTime objects. +- [#455](https://github.com/nautobot/nautobot-app-golden-config/pull/455) - Add metrics for Golden Config app. +- [#485](https://github.com/nautobot/nautobot-app-golden-config/pull/485) - Custom compliance for CLI and JSON rules. +- [#487](https://github.com/nautobot/nautobot-app-golden-config/pull/487) - Implement native JSON support. +- [#527](https://github.com/nautobot/nautobot-app-golden-config/pull/527) - Add the ability to update Jinja environment setting from nautobot_config. +- [#558](https://github.com/nautobot/nautobot-app-golden-config/pull/558) - Updated Filters for various models, including adding an experimental `_isnull` on DateTime objects. ### Changed -- [#485](https://github.com/nautobot/nautobot-plugin-golden-config/pull/485) - Changed the behavior of custom compliance to a boolean vs toggle between cli, json, and custom. +- [#485](https://github.com/nautobot/nautobot-app-golden-config/pull/485) - Changed the behavior of custom compliance to a boolean vs toggle between cli, json, and custom. ### Fixed -- [#505](https://github.com/nautobot/nautobot-plugin-golden-config/pull/505) - fixes imports and choice definitions in the compliance nornir play. -- [#513](https://github.com/nautobot/nautobot-plugin-golden-config/pull/513) - Fixed issue with native JSON support with `get_config_element` function. +- [#505](https://github.com/nautobot/nautobot-app-golden-config/pull/505) - fixes imports and choice definitions in the compliance nornir play. +- [#513](https://github.com/nautobot/nautobot-app-golden-config/pull/513) - Fixed issue with native JSON support with `get_config_element` function. diff --git a/docs/admin/release_notes/version_1.6.md b/docs/admin/release_notes/version_1.6.md index 259d890a..2b7adb51 100755 --- a/docs/admin/release_notes/version_1.6.md +++ b/docs/admin/release_notes/version_1.6.md @@ -9,41 +9,41 @@ ### Fixed -- [#668](https://github.com/nautobot/nautobot-plugin-golden-config/issue/668) - Removed unneeded lookup for GoldenConfigSetting +- [#668](https://github.com/nautobot/nautobot-app-golden-config/issue/668) - Removed unneeded lookup for GoldenConfigSetting ## v1.6.2 - 2023-09 ### Fixed -- [#621](https://github.com/nautobot/nautobot-plugin-golden-config/pull/621) - Moved jinja to be locally scoped, this was causing issues with Jinja filters based on import order. +- [#621](https://github.com/nautobot/nautobot-app-golden-config/pull/621) - Moved jinja to be locally scoped, this was causing issues with Jinja filters based on import order. ## v1.6.1 - 2023-09 ### Changed -- [#600](https://github.com/nautobot/nautobot-plugin-golden-config/pull/600) - Updated readme to include the additional use cases covered. +- [#600](https://github.com/nautobot/nautobot-app-golden-config/pull/600) - Updated readme to include the additional use cases covered. ### Fixed -- [#603](https://github.com/nautobot/nautobot-plugin-golden-config/pull/603) - Fix missing fields from the "AllDevicesGoldenConfig" Job. -- [#609](https://github.com/nautobot/nautobot-plugin-golden-config/pull/609) - Fixed issue where not all jinja filers, specifically netutils were being loaded into Jinja environment. -- [#609](https://github.com/nautobot/nautobot-plugin-golden-config/pull/609) - Fixed issues if a Job was never created since the feature was disabled, it would cause a stacktrace. -- [#609](https://github.com/nautobot/nautobot-plugin-golden-config/pull/609) - Fixed issue where in GoldenConfigSetting page, dynamic group selection would not show all of the eligible options. -- [#609](https://github.com/nautobot/nautobot-plugin-golden-config/pull/609) - Fixed issue where you could not fill in `jinja_env['undefined']` vars as a string, only a complex class. -- [#609](https://github.com/nautobot/nautobot-plugin-golden-config/pull/609) - Added the ability to generate remediation configurations and store in ConfigRemediation model +- [#603](https://github.com/nautobot/nautobot-app-golden-config/pull/603) - Fix missing fields from the "AllDevicesGoldenConfig" Job. +- [#609](https://github.com/nautobot/nautobot-app-golden-config/pull/609) - Fixed issue where not all jinja filers, specifically netutils were being loaded into Jinja environment. +- [#609](https://github.com/nautobot/nautobot-app-golden-config/pull/609) - Fixed issues if a Job was never created since the feature was disabled, it would cause a stacktrace. +- [#609](https://github.com/nautobot/nautobot-app-golden-config/pull/609) - Fixed issue where in GoldenConfigSetting page, dynamic group selection would not show all of the eligible options. +- [#609](https://github.com/nautobot/nautobot-app-golden-config/pull/609) - Fixed issue where you could not fill in `jinja_env['undefined']` vars as a string, only a complex class. +- [#609](https://github.com/nautobot/nautobot-app-golden-config/pull/609) - Added the ability to generate remediation configurations and store in ConfigRemediation model ## v1.6.0 - 2023-09 ### Added -- [#573](https://github.com/nautobot/nautobot-plugin-golden-config/pull/573) - Added the ability to generate remediation configurations and store in ConfigRemediation model -- [#573](https://github.com/nautobot/nautobot-plugin-golden-config/pull/573) - Added the ability to generate configurations that you plan to deploy from a variety of methods, such as Remediation, intended, manual, etc. via the ConfigPlan model. -- [#573](https://github.com/nautobot/nautobot-plugin-golden-config/pull/573) - Added the ability to Deploy configurations from the ConfigPlan configurations to your network devices. -- [#578](https://github.com/nautobot/nautobot-plugin-golden-config/pull/578) - Updated ComplianceRule and ComplianceRule forms to include tags. +- [#573](https://github.com/nautobot/nautobot-app-golden-config/pull/573) - Added the ability to generate remediation configurations and store in ConfigRemediation model +- [#573](https://github.com/nautobot/nautobot-app-golden-config/pull/573) - Added the ability to generate configurations that you plan to deploy from a variety of methods, such as Remediation, intended, manual, etc. via the ConfigPlan model. +- [#573](https://github.com/nautobot/nautobot-app-golden-config/pull/573) - Added the ability to Deploy configurations from the ConfigPlan configurations to your network devices. +- [#578](https://github.com/nautobot/nautobot-app-golden-config/pull/578) - Updated ComplianceRule and ComplianceRule forms to include tags. ### Fixed -- [#585](https://github.com/nautobot/nautobot-plugin-golden-config/pull/585) - Remove Jquery dependency from Google APIs, inherit from Nautobot core instead. -- [#577](https://github.com/nautobot/nautobot-plugin-golden-config/pull/577) - Fixed various forms fields and filters fields. -- [#577](https://github.com/nautobot/nautobot-plugin-golden-config/pull/577) - Updated default has_sensitive_data boolean to False. -- [#577](https://github.com/nautobot/nautobot-plugin-golden-config/pull/577) - Added warning message on views when required jobs are not enabled. +- [#585](https://github.com/nautobot/nautobot-app-golden-config/pull/585) - Remove Jquery dependency from Google APIs, inherit from Nautobot core instead. +- [#577](https://github.com/nautobot/nautobot-app-golden-config/pull/577) - Fixed various forms fields and filters fields. +- [#577](https://github.com/nautobot/nautobot-app-golden-config/pull/577) - Updated default has_sensitive_data boolean to False. +- [#577](https://github.com/nautobot/nautobot-app-golden-config/pull/577) - Added warning message on views when required jobs are not enabled. diff --git a/docs/admin/release_notes/version_2.0.md b/docs/admin/release_notes/version_2.0.md index 85ab0852..81a2a53a 100755 --- a/docs/admin/release_notes/version_2.0.md +++ b/docs/admin/release_notes/version_2.0.md @@ -16,51 +16,51 @@ ### Fixed -- [#676](https://github.com/nautobot/nautobot-plugin-golden-config/pull/676) - Fixes docs for running config plan job in 2.0. -- [#680](https://github.com/nautobot/nautobot-plugin-golden-config/pull/680) - Resolve RTD build issue. -- [#684](https://github.com/nautobot/nautobot-plugin-golden-config/pull/684) - Fix repo sync not executing on any task failure. -- [#685](https://github.com/nautobot/nautobot-plugin-golden-config/pull/685) - Cherry-pick #669 - Removed unneeded lookup for GoldenConfigSetting. -- [#686](https://github.com/nautobot/nautobot-plugin-golden-config/pull/686) - Fix incorrect permissions. +- [#676](https://github.com/nautobot/nautobot-app-golden-config/pull/676) - Fixes docs for running config plan job in 2.0. +- [#680](https://github.com/nautobot/nautobot-app-golden-config/pull/680) - Resolve RTD build issue. +- [#684](https://github.com/nautobot/nautobot-app-golden-config/pull/684) - Fix repo sync not executing on any task failure. +- [#685](https://github.com/nautobot/nautobot-app-golden-config/pull/685) - Cherry-pick #669 - Removed unneeded lookup for GoldenConfigSetting. +- [#686](https://github.com/nautobot/nautobot-app-golden-config/pull/686) - Fix incorrect permissions. ### Changed -- [#658](https://github.com/nautobot/nautobot-plugin-golden-config/pull/658) - Cookie updated by NetworkToCode Cookie Drift Manager Tool -- [#671](https://github.com/nautobot/nautobot-plugin-golden-config/pull/671) - Finish Documentation Updates from Drift Manager +- [#658](https://github.com/nautobot/nautobot-app-golden-config/pull/658) - Cookie updated by NetworkToCode Cookie Drift Manager Tool +- [#671](https://github.com/nautobot/nautobot-app-golden-config/pull/671) - Finish Documentation Updates from Drift Manager ## v2.0.0 - 2023-09 ### Changed -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Updated `nautobot` to `2.0.0` and made associated changes. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed dispatcher_mapping to custom_dispatcher and constance settings. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed Config Compliance view to be based on model, not dynamic group and provide a `message` when they have drifted. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed the location of the config compliance view to be a tab on device objects. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed the linking on Configuration Overview to point to the detailed object to align with Nautobot standards. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Inverted Config Plan logic to not show Completed Config Plans by default and have a button to see them. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Change logic to always include jobs, regardless of which features are in use. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed several of the URL locations of views, based on migration to viewsets and overall simplification of code. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed models to better reflect actual state, such as not to allow nullable on characters and one-to-one from config compliance to device model. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed any date/time reference to be django's `make_aware`. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed Nornir Processor logic on failures to be recursive lookups. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Updated diff2html to 3.4.43. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Changed booleans to be consistent with Nautobot UI. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Pinned django-pivot to 1.8.1 as that returns a queryset. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Various cleanup updates such as moving to viewsets, hyperlinked_text, moving matplot code, using Nautobot provided Git capabilities, updating development environment to NTC standards, etc. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Updated `nautobot` to `2.0.0` and made associated changes. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed dispatcher_mapping to custom_dispatcher and constance settings. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed Config Compliance view to be based on model, not dynamic group and provide a `message` when they have drifted. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed the location of the config compliance view to be a tab on device objects. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed the linking on Configuration Overview to point to the detailed object to align with Nautobot standards. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Inverted Config Plan logic to not show Completed Config Plans by default and have a button to see them. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Change logic to always include jobs, regardless of which features are in use. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed several of the URL locations of views, based on migration to viewsets and overall simplification of code. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed models to better reflect actual state, such as not to allow nullable on characters and one-to-one from config compliance to device model. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed any date/time reference to be django's `make_aware`. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed Nornir Processor logic on failures to be recursive lookups. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Updated diff2html to 3.4.43. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Changed booleans to be consistent with Nautobot UI. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Pinned django-pivot to 1.8.1 as that returns a queryset. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Various cleanup updates such as moving to viewsets, hyperlinked_text, moving matplot code, using Nautobot provided Git capabilities, updating development environment to NTC standards, etc. ### Added -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Introduced constance settings for DEFAULT_FRAMEWORK, GET_CONFIG_FRAMEWORK, MERGE_CONFIG_FRAMEWORK, and REPLACE_CONFIG_FRAMEWORK. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added error code framework. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added a setting for default_deploy_status to allow that to be configurable. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added a job to sync dynamic group and config compliance model. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added a custom logger capability to be able to handle stdout as well as nautobot job logs. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added copy buttons in several locations to allow for getting configurations easier. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Added datasources yaml key to use network_driver but still backwards compatible to _slug. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Introduced constance settings for DEFAULT_FRAMEWORK, GET_CONFIG_FRAMEWORK, MERGE_CONFIG_FRAMEWORK, and REPLACE_CONFIG_FRAMEWORK. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added error code framework. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added a setting for default_deploy_status to allow that to be configurable. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added a job to sync dynamic group and config compliance model. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added a custom logger capability to be able to handle stdout as well as nautobot job logs. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added copy buttons in several locations to allow for getting configurations easier. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Added datasources yaml key to use network_driver but still backwards compatible to _slug. ### Removed -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Remove the already deprecated "Scope" in favor of dynamic groups. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Removed references to git repository tokens. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Removed management command to run jobs in favor of Nautobot Core's usage. -- [#575](https://github.com/nautobot/nautobot-plugin-golden-config/pull/575) - Removed platform_slug_map in favor of constance settings. \ No newline at end of file +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Remove the already deprecated "Scope" in favor of dynamic groups. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Removed references to git repository tokens. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Removed management command to run jobs in favor of Nautobot Core's usage. +- [#575](https://github.com/nautobot/nautobot-app-golden-config/pull/575) - Removed platform_slug_map in favor of constance settings. \ No newline at end of file diff --git a/docs/admin/troubleshooting/index.md b/docs/admin/troubleshooting/index.md index 6a5d8382..cda1bc2f 100644 --- a/docs/admin/troubleshooting/index.md +++ b/docs/admin/troubleshooting/index.md @@ -6,7 +6,7 @@ This is an ongoing effort, but the foundation has been built. Within the Nautobot ecosystem, you may see various errors, they are distributed between 3 libraries as followed. -| Error Range | Plugin Docs | +| Error Range | App Docs | | ----------- | ----------- | | E1001-E1999 | [Nornir Nautobot](https://docs.nautobot.com/projects/nornir-nautobot/en/latest/task/troubleshooting/) | | E2001-E2999 | [Nautobot Plugin Nornir](https://docs.nautobot.com/projects/plugin-nornir/en/latest/admin/troubleshooting/) | diff --git a/docs/admin/uninstall.md b/docs/admin/uninstall.md index 44cfc88a..e05cecae 100644 --- a/docs/admin/uninstall.md +++ b/docs/admin/uninstall.md @@ -4,7 +4,7 @@ Here you will find any steps necessary to cleanly remove the App from your Nauto ## Database Cleanup -Prior to removing the plugin from the `nautobot_config.py`, run the following command to roll back any migration specific to this plugin. +Prior to removing the app from the `nautobot_config.py`, run the following command to roll back any migration specific to this app. ```shell nautobot-server migrate nautobot_golden_config zero diff --git a/docs/admin/upgrade.md b/docs/admin/upgrade.md index f4192592..293a2314 100644 --- a/docs/admin/upgrade.md +++ b/docs/admin/upgrade.md @@ -4,11 +4,11 @@ Here you will find any steps necessary to upgrade the App in your Nautobot envir ## Upgrade Guide -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-golden-config` package via `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 app. Execute the command `nautobot-server post-upgrade` within the runtime environment of your Nautobot installation after updating the `nautobot-golden-config` package via `pip`. ## v1.0.0 -`v1.0.0` Provides a breaking change for the users running pre `1.0.0` code sourced from `develop` branch of the plugin. Only users of the `Backup Repository Matching Rule` and `Intended Repository Matching Rule` features are affected by following behavior: migration script will only migrate the first repository from the list into the new default settings. +`v1.0.0` Provides a breaking change for the users running pre `1.0.0` code sourced from `develop` branch of the app. Only users of the `Backup Repository Matching Rule` and `Intended Repository Matching Rule` features are affected by following behavior: migration script will only migrate the first repository from the list into the new default settings. Because of this specific behavior, please review your configuration and capture it before attempting to upgrade if using above features. diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md index 5ca961d4..16760ce2 100644 --- a/docs/dev/contributing.md +++ b/docs/dev/contributing.md @@ -6,7 +6,7 @@ The project is following Network to Code software development guidelines and is - Python linting and formatting: `black`, `pylint`, `bandit`, `flake8`, and `pydocstyle`. - YAML linting is done with `yamllint`. -- Django unit test to ensure the plugin is working properly. +- Django unit test to ensure the app is working properly. Documentation is built using [mkdocs](https://www.mkdocs.org/). The [Docker based development environment](dev_environment.md#docker-development-environment) automatically starts a container hosting a live version of the documentation website on [http://localhost:8001](http://localhost:8001) that auto-refreshes when you make any changes to your local files. diff --git a/docs/dev/dev_environment.md b/docs/dev/dev_environment.md index 49495441..11a2528f 100644 --- a/docs/dev/dev_environment.md +++ b/docs/dev/dev_environment.md @@ -127,8 +127,8 @@ Each command can be executed with `invoke `. All commands support the a flake8 Run flake8 to check that Python files adhere to its style standards. pydocstyle Run pydocstyle to validate docstring formatting adheres to NTC defined standards. pylint Run pylint code analysis. - tests Run all tests for this plugin. - unittest Run Django unit tests for the plugin. + tests Run all tests for this app. + unittest Run Django unit tests for the app. ``` ## Project Overview @@ -290,9 +290,9 @@ This will safely shut down all of your running Docker containers for this projec Your environment should now be fully setup, all necessary Docker containers are created and running, and you're logged into Nautobot in your web browser. Now what? -Now you can start developing your plugin in the project folder! +Now you can start developing your app in the project folder! -The magic here is the root directory is mounted inside your Docker containers when built and ran, so **any** changes made to the files in here are directly updated to the Nautobot plugin code running in Docker. This means that as you modify the code in your plugin folder, the changes will be instantly updated in Nautobot. +The magic here is the root directory is mounted inside your Docker containers when built and ran, so **any** changes made to the files in here are directly updated to the Nautobot app code running in Docker. This means that as you modify the code in your app folder, the changes will be instantly updated in Nautobot. !!! warning There are a few exceptions to this, as outlined in the section [To Rebuild or Not To Rebuild](#to-rebuild-or-not-to-rebuild). @@ -316,7 +316,7 @@ When trying to debug an issue, one helpful thing you can look at are the logs wi !!! info Want to limit the log output even further? Use the `--tail <#>` command line argument in conjunction with `-f`. -So for example, our plugin is named `nautobot-golden-config`, the command would most likely be `docker logs nautobot_golden_config_nautobot_1 -f`. You can find the name of all running containers via `docker ps`. +So for example, our app is named `nautobot-golden-config`, the command would most likely be `docker logs nautobot_golden_config_nautobot_1 -f`. You can find the name of all running containers via `docker ps`. If you want to view the logs specific to the worker container, simply use the name of that container instead. @@ -342,7 +342,7 @@ Once completed, the new/updated environment variables should now be live. ### Installing Additional Python Packages -If you want your plugin to leverage another available Nautobot plugin or another Python package, you can easily add them into your Docker environment. +If you want your app to leverage another available Nautobot app or another Python package, you can easily add them into your Docker environment. ```bash ➜ poetry shell @@ -357,18 +357,18 @@ Once the dependencies are resolved, stop the existing containers, rebuild the Do ➜ invoke start ``` -### Installing Additional Nautobot Plugins +### Installing Additional Nautobot Apps -Let's say for example you want the new plugin you're creating to integrate into Slack. To do this, you will want to integrate into the existing Nautobot ChatOps Plugin. +Let's say for example you want the new app you're creating to integrate into Slack. To do this, you will want to integrate into the existing Nautobot ChatOps App. ```bash ➜ poetry shell ➜ poetry add nautobot-chatops ``` -Once you activate the virtual environment via Poetry, you then tell Poetry to install the new plugin. +Once you activate the virtual environment via Poetry, you then tell Poetry to install the new app. -Before you continue, you'll need to update the file `development/nautobot_config.py` accordingly with the name of the new plugin under `PLUGINS` and any relevant settings as necessary for the plugin under `PLUGINS_CONFIG`. Since you're modifying the underlying OS (not just Django files), you need to rebuild the image. This is a similar process to updating environment variables, which was explained earlier. +Before you continue, you'll need to update the file `development/nautobot_config.py` accordingly with the name of the new app under `PLUGINS` and any relevant settings as necessary for the app under `PLUGINS_CONFIG`. Since you're modifying the underlying OS (not just Django files), you need to rebuild the image. This is a similar process to updating environment variables, which was explained earlier. ```bash ➜ invoke stop @@ -376,7 +376,7 @@ Before you continue, you'll need to update the file `development/nautobot_config ➜ invoke start ``` -Once the containers are up and running, you should now see the new plugin installed in your Nautobot instance. +Once the containers are up and running, you should now see the new app installed in your Nautobot instance. !!! note You can even launch an `ngrok` service locally on your laptop, pointing to port 8080 (such as for chatops development), and it will point traffic directly to your Docker images. diff --git a/docs/user/app_feature_backup.md b/docs/user/app_feature_backup.md index 8ba9113e..2dff5b27 100644 --- a/docs/user/app_feature_backup.md +++ b/docs/user/app_feature_backup.md @@ -27,7 +27,7 @@ Backup repositories must first be configured under **Extensibility -> Git Reposi ### Backup Path Template -The `backup_path_template` setting gives you a way to dynamically place each device's configuration file in the repository file structure. This setting uses the GraphQL query configured for the plugin. It works in a similar way to the Backup Repository Matching Rule above. Since the setting uses a GraphQL query, any valid Device model method is available. The plugin renders the values from the query, using Jinja2, to the relative path and file name in which to store a given device's configuration inside its backup repository. This may seem complicated, but the equivalent of `obj` by example would be: +The `backup_path_template` setting gives you a way to dynamically place each device's configuration file in the repository file structure. This setting uses the GraphQL query configured for the app. It works in a similar way to the Backup Repository Matching Rule above. Since the setting uses a GraphQL query, any valid Device model method is available. The app renders the values from the query, using Jinja2, to the relative path and file name in which to store a given device's configuration inside its backup repository. This may seem complicated, but the equivalent of `obj` by example would be: ```python obj = Device.objects.get(name="nyc-rt01") @@ -62,7 +62,7 @@ PLUGINS_CONFIG = { To start a backup job manually: -1. Navigate to the Plugin Home (Golden Config->Home), with Home being in the `Golden Configuration` section +1. Navigate to the App Home (Golden Config->Home), with Home being in the `Golden Configuration` section 2. Select _Execute_ on the upper right buttons, then _Backup_ 3. Fill in the data that you wish to have backed up 4. Select _Run Job_ diff --git a/docs/user/app_feature_compliance.md b/docs/user/app_feature_compliance.md index 1647370d..1cfe51eb 100644 --- a/docs/user/app_feature_compliance.md +++ b/docs/user/app_feature_compliance.md @@ -37,7 +37,7 @@ To start a compliance job manually: ## Configuration Compliance Settings -Configuration compliance requires the Git Repo settings for `config backups` and `intended configs`--which are covered in their respective sections--regardless if they are actually managed via the plugin or not. The same is true for the `Backup Path` and `Intended Path`. +Configuration compliance requires the Git Repo settings for `config backups` and `intended configs`--which are covered in their respective sections--regardless if they are actually managed via the app or not. The same is true for the `Backup Path` and `Intended Path`. The Configuration compliance rule map must be created per the operator/user. You can find these configurations via `Golden Config -> Compliance Rules` links, which brings up the specific configurations. @@ -65,7 +65,7 @@ For JSON based configs, the match is based on JSON's structure top level key nam If the data is accidentally "corrupted" with a bad tested match, simply delete the devices an re-run the compliance process. !!! note - The mapping of "network_os" as defined by netutils is provided via the plugin settings in your nautobot_config.py, and documented on the primary Readme. + The mapping of "network_os" as defined by netutils is provided via the app settings in your nautobot_config.py, and documented on the primary Readme. ## Compliance View diff --git a/docs/user/app_feature_compliancecustom.md b/docs/user/app_feature_compliancecustom.md index 8f43b914..43e2f958 100644 --- a/docs/user/app_feature_compliancecustom.md +++ b/docs/user/app_feature_compliancecustom.md @@ -2,8 +2,8 @@ ## Introduction Custom compliance is a powerful method to alter the default behavior and results of the natively provided `CLI` and `JSON` config type based configuration compliance. -The high level idea is to provide a Python code containing custom logic defined by the User. This code is called by the Golden Configuration Plugin in the compliance process, -allowing the user to change the default behavior of the Golden Configuration Plugin. +The high level idea is to provide a Python code containing custom logic defined by the User. This code is called by the Golden Configuration App in the compliance process, +allowing the user to change the default behavior of the Golden Configuration App. ## Caveats @@ -21,7 +21,7 @@ state vs actual state, we are conscious that this may not always be a viable sol Providing additional opinionated solutions is both not in-line with the intention of the project nor is it feasible to provide a solution that will work for many people. For those reasons, it was decided to create an extendible interface for developers/operators to create their custom compliance logic. -Finally, it is understood that one of the key values provided by the Golden Config plugin is the visualization of the compliance and quick access to the tooling. Providing the interface to `get_custom_compliance` function allows the developers/operators the ability to get their own compliance process integrated with the user experience provided by the plugin. +Finally, it is understood that one of the key values provided by the Golden Config app is the visualization of the compliance and quick access to the tooling. Providing the interface to `get_custom_compliance` function allows the developers/operators the ability to get their own compliance process integrated with the user experience provided by the app. ## The Interface diff --git a/docs/user/app_feature_intended.md b/docs/user/app_feature_intended.md index 7023f2d7..1ccc3ddc 100644 --- a/docs/user/app_feature_intended.md +++ b/docs/user/app_feature_intended.md @@ -2,11 +2,11 @@ ## Configuration Generation -The Golden Config plugin **Intended Configuration** job generates intended state files for each device in the plugin setting's configured Dynamic Group. An intended state files contain the output from rendering the device's Source of Truth Aggregation values through the Jinja2 templates used by the plugin. +The Golden Config app **Intended Configuration** job generates intended state files for each device in the app setting's configured Dynamic Group. An intended state files contain the output from rendering the device's Source of Truth Aggregation values through the Jinja2 templates used by the app. -The job itself is a Nornir play which uses a single Jinja2 template per device. Source of Truth Aggregation data comes from the GraphQL query configured in the Golden Config plugin's settings. An important component of the SoT Aggregation data are the `config_context` values. `config_context` should contain a vendor-neutral, JSON structured representation of a device's configuration values: a list of NTP/AAA/Syslog servers, common VRFs, etc. See [Config Contexts](https://docs.nautobot.com/projects/core/en/latest/additional-features/config-contexts/#configuration-contexts) for more information. +The job itself is a Nornir play which uses a single Jinja2 template per device. Source of Truth Aggregation data comes from the GraphQL query configured in the Golden Config app's settings. An important component of the SoT Aggregation data are the `config_context` values. `config_context` should contain a vendor-neutral, JSON structured representation of a device's configuration values: a list of NTP/AAA/Syslog servers, common VRFs, etc. See [Config Contexts](https://docs.nautobot.com/projects/core/en/latest/additional-features/config-contexts/#configuration-contexts) for more information. -The Source of Truth Aggregation feature of the plugin must be enabled for the plugin to generate intended configuration state output. +The Source of Truth Aggregation feature of the app must be enabled for the app to generate intended configuration state output. There can only be a single Jinja2 template per device. Device configurations can become daunting to create via a template, if you try to place all of the logic for a device's configuration inside a single Jinja2 file. These template files can quickly become too complex to maintain. So, it is often advantageous to break configurations into smaller feature-oriented snippets, each contained in their own discrete template file. Operators often keep their main, top-level, template simple and easy to maintain by only placing include statements in it: @@ -35,11 +35,11 @@ In these examples, `/services.j2`, `/ntp.j2`, etc. could contain the actual Jinj ## Adding Jinja2 Filters to the Environment. -This plugin follows [Nautobot](https://docs.nautobot.com/projects/core/en/stable/plugins/development/#including-jinja2-filters) in relying on [django_jinja](https://niwinz.github.io/django-jinja/latest/) for customizing the Jinja2 Environment. Currently, only filters in the `django_jinja` Environment are passed along to the Jinja2 Template Environment used by Nornir to render the config template. +This app follows [Nautobot](https://docs.nautobot.com/projects/core/en/stable/plugins/development/#including-jinja2-filters) in relying on [django_jinja](https://niwinz.github.io/django-jinja/latest/) for customizing the Jinja2 Environment. Currently, only filters in the `django_jinja` Environment are passed along to the Jinja2 Template Environment used by Nornir to render the config template. ### Adding Filters In Nautobot Config -Nautobot documents using the `@django_jinja.library.filter` decorator to register functions as filters with `django_jinja`. However, users of plugins are not able to define plugins in the specified jinja2 filter file that is loaded into the Jinja2 Environment. +Nautobot documents using the `@django_jinja.library.filter` decorator to register functions as filters with `django_jinja`. However, users of apps are not able to define apps in the specified jinja2 filter file that is loaded into the Jinja2 Environment. There are several alternative ways to have functions registered as filters in the `django_jinja` environment; below demonstrates defining decorated functions in a separate file, and then importing them in the `nautobot_config.py` file. This method requires that the file is in a path that is available to Nautobot's python environment. @@ -98,7 +98,7 @@ In order to generate the intended configurations at least two repositories are n !!! note Only use a Intended Repository Matching Rule if you have **more than one** intended repository. It is **not needed** if you only have one repository. The operator is expected to ensure that every device results in a successful matching rule (or that device will fail to render a config). -The `intended_match_rule` setting allows you to match a given `Device` Django ORM object to a backup Git repository. This field should contain a Jinja2-formatted template. The plugin populates the variables in the Jinja2 template via the GraphQL query configured on the plugin. +The `intended_match_rule` setting allows you to match a given `Device` Django ORM object to a backup Git repository. This field should contain a Jinja2-formatted template. The app populates the variables in the Jinja2 template via the GraphQL query configured on the app. This is exactly the same concept as described in [Backup Repository Matching Rule](./app_feature_backup.md#repository-matching-rule), and better described there. diff --git a/docs/user/app_feature_remediation.md b/docs/user/app_feature_remediation.md index 61c9c0cf..4cde54f0 100644 --- a/docs/user/app_feature_remediation.md +++ b/docs/user/app_feature_remediation.md @@ -1,7 +1,7 @@ # Navigating Configuration Remediation Automated network configuration remediation is a systematic approach that leverages technology and processes to address and rectify configuration issues in network devices. -It involves the use of the Golden Configuration plugin to understand the current configuration state, compare it against the intended configuration state, and automatically generate remediation data. +It involves the use of the Golden Configuration app to understand the current configuration state, compare it against the intended configuration state, and automatically generate remediation data. Automated network configuration remediation improves efficiency by eliminating manual efforts and reducing the risk of human errors. It enables rapid response to security vulnerabilities, minimizes downtime, and enhances compliance with regulatory and industry standards. diff --git a/docs/user/app_feature_sotagg.md b/docs/user/app_feature_sotagg.md index 8cb29722..8de81d63 100644 --- a/docs/user/app_feature_sotagg.md +++ b/docs/user/app_feature_sotagg.md @@ -18,11 +18,11 @@ The query starts with exactly `query ($device_id: ID!)`. This is to help fail fa Note that the GraphQL query returned is modified to remove the root key of `device`, so instead of all data being within device, such as `{"device": {"location": {"name": "Jersey City"}}}`, it is simply `{"location": {"name": "Jersey City"}}` as an example. -It is helpful to make adjustments to the query, and then view the data from the Plugin's home page and clicking on a given device's `code-json` icon. +It is helpful to make adjustments to the query, and then view the data from the App's home page and clicking on a given device's `code-json` icon. ## Transposer Function -The transposer function is an optional function to make arbitrary changes to the data after the fact. There is a plugin configuration that allows the +The transposer function is an optional function to make arbitrary changes to the data after the fact. There is a app configuration that allows the operator to point to a function within the python path by a string. The function will receive a single variable, that by convention should be called `data`. The function should return a valid Python json serializable data structure. ```python @@ -37,7 +37,7 @@ def transposer(data): While the example transposer is silly and untested, it provides the structure for which a transposer can be used. The possibilities are obviously endless, such as reaching out to an external system, but operators should use caution not to overload complexity into the transposer. -The configuration required in the plugin configuration is as described below. +The configuration required in the app configuration is as described below. ```python PLUGINS_CONFIG["nautobot_golden_config"]["sot_agg_transposer"] = "nautobot_golden_config.transposer.transposer" diff --git a/docs/user/app_getting_started.md b/docs/user/app_getting_started.md index 22b3a82d..476ee0a0 100644 --- a/docs/user/app_getting_started.md +++ b/docs/user/app_getting_started.md @@ -10,7 +10,7 @@ To install the App, please follow the instructions detailed in the [Installation ### Backup Configuration -Follow the steps below to get up and running for the configuration backup element of the plugin. +Follow the steps below to get up and running for the configuration backup element of the app. 1. Enable the feature in the `PLUGIN_SETTINGS`. The configuration should have `"enable_backup": True` set in the `PLUGINS_CONFIG` dictionary for `nautobot_golden_config`. @@ -21,7 +21,7 @@ Follow the steps below to get up and running for the configuration backup elemen 3. Make sure to select the **Provides** called `backup configs`. 4. Click Create. -3. Next, make sure to create new or update existing Plugins **Settings** with the backup details. +3. Next, make sure to create new or update existing Apps **Settings** with the backup details. 1. Navigate to `Golden Config -> Settings` under the Golden Configuration Section. 2. Create new or select one of the existing `Settings` objects 3. Fill out the Backup Repository. (The dropdown will show the repository that was just created.) @@ -45,13 +45,13 @@ Follow the steps below to get up and running for the configuration backup elemen ### Intended Configuration -Follow the steps below to get up and running for the intended configuration element of the plugin. +Follow the steps below to get up and running for the intended configuration element of the app. !!! note - Intended Configuration requires the `enable_intended` and `enabled_sotAgg` plugin features to be used. + Intended Configuration requires the `enable_intended` and `enabled_sotAgg` app features to be used. !!! note - If Secret Group is used for the Repositories the secrets type HTTP(S) is required for this plugin. + If Secret Group is used for the Repositories the secrets type HTTP(S) is required for this app. 1. Enable the feature in the `PLUGIN_SETTINGS`. The configuration should have `"enable_intended": True` set in the `PLUGINS_CONFIG` dictionary for `nautobot_golden_config`. @@ -70,7 +70,7 @@ Follow the steps below to get up and running for the intended configuration elem 3. Make sure to select the **Provides** called `jinja templates`. 4. Click Create. -4. Next, make sure to create new or update existing Plugins **Settings** with the intended and jinja2 template details. +4. Next, make sure to create new or update existing Apps **Settings** with the intended and jinja2 template details. 1. Navigate to `Golden Config -> Settings` under the Golden Configuration Section. 2. Create new or select one of the existing `Settings` objects @@ -126,7 +126,7 @@ Compliance requires Backups and Intended Configurations in order to be executed. ### Config Remediation -Follow the steps below to get up and running for the configuration remediation element of the plugin. +Follow the steps below to get up and running for the configuration remediation element of the app. 1. Navigate to `Golden Config -> Compliance Rules`. 2. Select the rules in which you'd like to enable remediation on. @@ -138,7 +138,7 @@ Follow the steps below to get up and running for the configuration remediation e ### Config Plans -Follow the steps below to get up and running for the configuration plans element of the plugin. +Follow the steps below to get up and running for the configuration plans element of the app. 1. Enable the feature in the `PLUGIN_SETTINGS`. The configuration should have `"enable_plan": True` set in the `PLUGINS_CONFIG` dictionary for `nautobot_golden_config`. 2. Follow the steps in [Compliance](#compliance). @@ -160,7 +160,7 @@ Follow the steps below to get up and running for the configuration plans element ### Config Deploy -Follow the steps below to get up and running for the configuration deployment element of the plugin. +Follow the steps below to get up and running for the configuration deployment element of the app. 1. Enable the feature in the `PLUGIN_SETTINGS`. The configuration should have `"enable_deploy": True` set in the `PLUGINS_CONFIG` dictionary for `nautobot_golden_config`. 2. Follow the steps in [Config Plans](#config-plans). diff --git a/docs/user/app_overview.md b/docs/user/app_overview.md index 82d05dbe..a2192628 100644 --- a/docs/user/app_overview.md +++ b/docs/user/app_overview.md @@ -13,7 +13,7 @@ When engineers are starting their network automation journey, everybody asks whe - Multiple individuals independently making changes - Mergers and acquisitions -Thankfully, this issue can be addressed without making any changes on your devices. You might ask, “How do I do that?” That is where the Golden Configuration plugin for Nautobot comes in. The Golden Configuration plugin is comprised of four components: +Thankfully, this issue can be addressed without making any changes on your devices. You might ask, “How do I do that?” That is where the Golden Configuration app for Nautobot comes in. The Golden Configuration app is comprised of four components: - Configuration Backup - Source of Truth Aggregation diff --git a/docs/user/app_use_cases.md b/docs/user/app_use_cases.md index a9d2c875..e501af87 100644 --- a/docs/user/app_use_cases.md +++ b/docs/user/app_use_cases.md @@ -28,7 +28,7 @@ components against all of the devices. ### Jobs -There are a series of Jobs that are registered via the Plugin. They can be viewed from the standard Jobs view. +There are a series of Jobs that are registered via the App. They can be viewed from the standard Jobs view. ![Job Overview](../images/job-overview.png) @@ -38,8 +38,8 @@ Each Job attempts to provide sane error handling, and respects the `debug` flag ### Application Settings -The golden configuration plugin settings can be found by navigating to `Golden Config -> Settings` button. Select one of the Settings, under the `Golden Configuration` section. -Since Golden Configuration Plugin version 1.0, the plugin allows for multiple settings to be configured by the User. +The golden configuration app settings can be found by navigating to `Golden Config -> Settings` button. Select one of the Settings, under the `Golden Configuration` section. +Since Golden Configuration App version 1.0, the app allows for multiple settings to be configured by the User. Each of the settings, has the individual repositories and configuration details, as well as a Dynamic Group. You could use a combination of settings to customize your Configuration Compliance behavior. Settings have a name and a weight. The weight parameter indicates the priority of given Settings - the higher the weight, the device matching the Dynamic Group defined will be assigned to the scope. @@ -167,7 +167,7 @@ The steps to add the variables to your environment are outside the scope of this ### Git Settings -The plugin makes heavy use of the Nautobot git data sources feature. There are up to three repositories used in the application. This set of instructions will walk an operator through setting up the backup repository. The steps are the same, except for the "Provides" field name chosen. +The app makes heavy use of the Nautobot git data sources feature. There are up to three repositories used in the application. This set of instructions will walk an operator through setting up the backup repository. The steps are the same, except for the "Provides" field name chosen. In order to setup this repository, go to Nautobot and navigate to the Data Sources Git integration. `Extensibility -> Git Repositories`. @@ -202,22 +202,22 @@ Once you click `Create` and the repository syncs, the main page will now show th For their respective features, the "Provides" field could be backup intended configs and jinja templates. -### Plugins Buttons +### Apps Buttons -The plugins buttons provides you with the ability to navigate to Run the script, overview report, and detailed report. +The apps buttons provides you with the ability to navigate to Run the script, overview report, and detailed report. ### Run Script -This can be accessed via the Plugins drop-down via `Run Script` button of the `Home` view, the user will be provided a form of the Job (as described +This can be accessed via the Apps drop-down via `Run Script` button of the `Home` view, the user will be provided a form of the Job (as described above), which will allow the user to limit the scope of the request. ### Device Template Content -The plugin makes use of template content `right_page` in order to use display in-line the status of that device in the traditional Nautobot view. From here you can click the link to see the detail compliance view. +The app makes use of template content `right_page` in order to use display in-line the status of that device in the traditional Nautobot view. From here you can click the link to see the detail compliance view. ### Location Template Content -The plugin makes use of template content `right_page` in order to use display in-line the status of that entire location in the traditional Nautobot view. This sums the total for all locations for parent locations. +The app makes use of template content `right_page` in order to use display in-line the status of that entire location in the traditional Nautobot view. This sums the total for all locations for parent locations. ### API @@ -231,11 +231,11 @@ garbage collection and it is up to the operator to remove such data. ### Network Operating System Support The version of OS's supported is documented in the [FAQ](./faq.md) and is controlled the platform network_driver. The platform network_driver must be exactly as expected or leverage -a configuration option--which is described the the FAQ--for the plugin to work. +a configuration option--which is described the the FAQ--for the app to work. ### Use-cases and common workflows -This plugin enable four (4) key use cases. +This app enable four (4) key use cases. 1. **Configuration Backups** - Is a Nornir process to connect to devices, optionally parse out lines/secrets, backup the configuration, and save to a Git repository. 2. **Intended Configuration** - Is a Nornir process to generate configuration based on a Git repo of Jinja files to combine with a GraphQL generated data and a Git repo to store the intended configuration. @@ -247,7 +247,7 @@ This plugin enable four (4) key use cases. ## Screenshots -There are many features and capabilities the plugin provides into the Nautobot ecosystem. The following screenshots are intended to provide a quick visual overview of some of these features. +There are many features and capabilities the app provides into the Nautobot ecosystem. The following screenshots are intended to provide a quick visual overview of some of these features. The golden configuration is driven by jobs that run a series of tasks and the result is captured in this overview. diff --git a/docs/user/faq.md b/docs/user/faq.md index 03c209e2..5ac4eef0 100644 --- a/docs/user/faq.md +++ b/docs/user/faq.md @@ -8,7 +8,7 @@ Any other interpretations of how compliance should be viewed are encouraged to u ## _Why don't the configurations match like the vendor cli?_ -A vendor processes configuration understanding constructs such as knowing that `int g0/0` and `interface GigabitEthernet0/0` are the same. Each one of these rules a subject to a given vendor's OS implementation. The ability to track these changes for all vendors/OS/versions is nearly impossible. Additionally, this practice would be error prone and not follow the principal of least astonishment. Notwithstanding a major change in the network industry, adjusting this strategy is outside the scope of the plugin. +A vendor processes configuration understanding constructs such as knowing that `int g0/0` and `interface GigabitEthernet0/0` are the same. Each one of these rules a subject to a given vendor's OS implementation. The ability to track these changes for all vendors/OS/versions is nearly impossible. Additionally, this practice would be error prone and not follow the principal of least astonishment. Notwithstanding a major change in the network industry, adjusting this strategy is outside the scope of the app. Instead, the operator is required to ensure their configurations match exactly as the configurations show in the running configuration. This includes all spacing, special characters, or literally anything that result in a string comparison not returning true. @@ -20,7 +20,7 @@ On a technical level, those changes enable the model `GoldenConfig` to *not* fil ## _Why aren't configurations generated or compliance generated real time?_ -The plugin make no assumptions about your intention and expects the operator to manage the configurations as they see fit. As as example, in preparation for a change, one may update data to reflect these changes, but not want to generate or run compliance against these configurations. +The app make no assumptions about your intention and expects the operator to manage the configurations as they see fit. As as example, in preparation for a change, one may update data to reflect these changes, but not want to generate or run compliance against these configurations. Additionally, configurations generated would have to either update the Git Repo immediately or generate locally only and not update the Git Repo, both of which may not be as the user expected. @@ -30,7 +30,7 @@ The current design allows for the maximum amount of use cases and make little as Backup configurations solutions are simple to start with and grow to hundreds or thousands of requests. That added complexity is not something that is in scope for the project. -Many people will have different opinions about what should or should not be filtered or substituted. Providing the flexibility allows the user to have it operate as they intend it, without burdening the plugins goals. +Many people will have different opinions about what should or should not be filtered or substituted. Providing the flexibility allows the user to have it operate as they intend it, without burdening the apps goals. ## _Why not predefine the configuration feature map?_ @@ -97,7 +97,7 @@ In many use cases, this can be extended with a custom dispatcher for nornir task ## _Why not provide the corrective configurations?_ -Configuration enforcement is a difficult problem to attack. While potentially could integrate with a system to provide the enforcement, this is currently out-of-scope for the plugin. +Configuration enforcement is a difficult problem to attack. While potentially could integrate with a system to provide the enforcement, this is currently out-of-scope for the app. ## _Why does the compliance section scroll so much?_ @@ -139,7 +139,7 @@ django.core.signing.BadSignature: Signature "b'A9QMEEeCk2+tAc6naf2KDiZBvACNWGNHG ERROR: 1 ``` -If you receive this error, the issue is the secret key has been changed, and **does not** have anything to do with the Golden Config plugin. You can either delete the entries from your data source and the reference to those in the Golden Config settings or revert the secret key back so it matches the original deployment. Any issues opened will be closed and this faq referred to. If you still need help, feel free to join the Slack community. +If you receive this error, the issue is the secret key has been changed, and **does not** have anything to do with the Golden Config app. You can either delete the entries from your data source and the reference to those in the Golden Config settings or revert the secret key back so it matches the original deployment. Any issues opened will be closed and this faq referred to. If you still need help, feel free to join the Slack community. ## _I got a `preemptively failed` error, but I know my system is setup correctly?_ diff --git a/docs/user/troubleshooting/troubleshoot_general.md b/docs/user/troubleshooting/troubleshoot_general.md index 1aefdd46..452ae3c6 100755 --- a/docs/user/troubleshooting/troubleshoot_general.md +++ b/docs/user/troubleshooting/troubleshoot_general.md @@ -67,4 +67,4 @@ If none of these troubleshooting steps helped identify the problem please visit ### Detailed Diagrams -Golden config flow diagrams are available on the repositories [wiki](https://github.com/nautobot/nautobot-plugin-golden-config/wiki#diagrams). +Golden config flow diagrams are available on the repositories [wiki](https://github.com/nautobot/nautobot-app-golden-config/wiki#diagrams). diff --git a/mkdocs.yml b/mkdocs.yml index a392bdfc..f08d1492 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,10 +1,10 @@ --- dev_addr: "127.0.0.1:8001" -edit_uri: "edit/main/nautobot-plugin-golden-config/docs" +edit_uri: "edit/main/nautobot-app-golden-config/docs" site_dir: "nautobot_golden_config/static/nautobot_golden_config/docs" site_name: "Nautobot Golden Configuration Documentation" site_url: "https://docs.nautobot.com/projects/golden-config/en/latest/" -repo_url: "https://github.com/nautobot/nautobot-plugin-golden-config" +repo_url: "https://github.com/nautobot/nautobot-app-golden-config" copyright: "Copyright © The Authors" theme: name: "material" diff --git a/nautobot_golden_config/__init__.py b/nautobot_golden_config/__init__.py index 196b8f98..a671301d 100644 --- a/nautobot_golden_config/__init__.py +++ b/nautobot_golden_config/__init__.py @@ -1,4 +1,4 @@ -"""Plugin declaration for nautobot_golden_config.""" +"""App declaration for nautobot_golden_config.""" # Metadata is inherited from Nautobot. If not including Nautobot in the environment, this should be added from importlib import metadata @@ -11,7 +11,7 @@ class GoldenConfig(NautobotAppConfig): - """Plugin configuration for the nautobot_golden_config plugin.""" + """App configuration for the nautobot_golden_config app.""" name = "nautobot_golden_config" verbose_name = "Golden Configuration" diff --git a/nautobot_golden_config/api/__init__.py b/nautobot_golden_config/api/__init__.py index e1375b86..c0f2c670 100644 --- a/nautobot_golden_config/api/__init__.py +++ b/nautobot_golden_config/api/__init__.py @@ -1 +1 @@ -"""REST API module for nautobot_golden_config plugin.""" +"""REST API module for nautobot_golden_config app.""" diff --git a/nautobot_golden_config/api/serializers.py b/nautobot_golden_config/api/serializers.py index 8c1bbff2..f3a1c103 100644 --- a/nautobot_golden_config/api/serializers.py +++ b/nautobot_golden_config/api/serializers.py @@ -1,4 +1,4 @@ -"""REST API serializer capabilities for graphql plugin.""" +"""REST API serializer capabilities for graphql app.""" # pylint: disable=too-many-ancestors from rest_framework import serializers diff --git a/nautobot_golden_config/datasources.py b/nautobot_golden_config/datasources.py index 8041df77..c8953736 100644 --- a/nautobot_golden_config/datasources.py +++ b/nautobot_golden_config/datasources.py @@ -1,4 +1,4 @@ -"""Data source plugin extension to register additional git repo types.""" +"""Data source app extension to register additional git repo types.""" import os import yaml diff --git a/nautobot_golden_config/forms.py b/nautobot_golden_config/forms.py index 8c61e263..f8e8ff19 100644 --- a/nautobot_golden_config/forms.py +++ b/nautobot_golden_config/forms.py @@ -502,7 +502,7 @@ class ConfigPlanForm(NautobotModelForm): tenant = forms.DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), required=False, query_params={"tenant_group": "$tenant_group"} ) - # Requires https://github.com/nautobot/nautobot-plugin-golden-config/issues/430 + # Requires https://github.com/nautobot/nautobot-app-golden-config/issues/430 location = forms.DynamicModelMultipleChoiceField(queryset=Location.objects.all(), required=False) rack_group = forms.DynamicModelMultipleChoiceField( queryset=RackGroup.objects.all(), required=False, query_params={"location": "$location"} diff --git a/nautobot_golden_config/jobs.py b/nautobot_golden_config/jobs.py index 6f3c5be7..ec6c7f16 100644 --- a/nautobot_golden_config/jobs.py +++ b/nautobot_golden_config/jobs.py @@ -41,7 +41,7 @@ def get_refreshed_repos(job_obj, repo_type, data=None): - """Small wrapper to pull latest branch, and return a GitRepo plugin specific object.""" + """Small wrapper to pull latest branch, and return a GitRepo app specific object.""" devices = get_job_filter(data) dynamic_groups = DynamicGroup.objects.exclude(golden_config_setting__isnull=True) repository_records = set() diff --git a/nautobot_golden_config/metrics.py b/nautobot_golden_config/metrics.py index 61b2a2a4..80ced35f 100644 --- a/nautobot_golden_config/metrics.py +++ b/nautobot_golden_config/metrics.py @@ -1,4 +1,4 @@ -"""Nautobot Golden Config plugin application level metrics .""" +"""Nautobot Golden Config app application level metrics .""" from django.conf import settings from django.db.models import Count, F, Q from nautobot.dcim.models import Device diff --git a/nautobot_golden_config/models.py b/nautobot_golden_config/models.py index b7c75ca7..62023a74 100644 --- a/nautobot_golden_config/models.py +++ b/nautobot_golden_config/models.py @@ -25,7 +25,7 @@ ERROR_MSG = ( "There was an issue with the data that was returned by your get_custom_compliance function. " "This is a local issue that requires the attention of your systems administrator and not something " - "that can be fixed within the Golden Config plugin. " + "that can be fixed within the Golden Config app. " ) MISSING_MSG = ( ERROR_MSG + "Specifically the `{}` key was not found in value the get_custom_compliance function provided." @@ -182,7 +182,7 @@ def _get_hierconfig_remediation(obj): msg = ( "There was an issue attempting to import the custom function of" f"{PLUGIN_CFG[custom_function]}, this is expected with a local configuration issue " - "and not related to the Golden Configuration Plugin, please contact your system admin for further details" + "and not related to the Golden Configuration App, please contact your system admin for further details" ) raise Exception(msg).with_traceback(error.__traceback__) @@ -531,7 +531,7 @@ class Meta: Provide ordering used in tables and get_device_to_settings_map. Sorting on weight is performed from the highest weight value to the lowest weight value. - This is to ensure only one plugin settings could be applied per single device based on priority and name. + This is to ensure only one app settings could be applied per single device based on priority and name. """ verbose_name = "Golden Config Setting" diff --git a/nautobot_golden_config/navigation.py b/nautobot_golden_config/navigation.py index 204cc721..cad08c5c 100644 --- a/nautobot_golden_config/navigation.py +++ b/nautobot_golden_config/navigation.py @@ -1,4 +1,4 @@ -"""Add the configuration compliance buttons to the Plugins Navigation.""" +"""Add the configuration compliance buttons to the Apps Navigation.""" from nautobot.apps.ui import NavMenuAddButton, NavMenuGroup, NavMenuItem, NavMenuTab diff --git a/nautobot_golden_config/nornir_plays/config_deployment.py b/nautobot_golden_config/nornir_plays/config_deployment.py index 0f5d0380..b59502fd 100644 --- a/nautobot_golden_config/nornir_plays/config_deployment.py +++ b/nautobot_golden_config/nornir_plays/config_deployment.py @@ -36,7 +36,7 @@ def run_deployment(task: Task, logger: logging.Logger, config_plan_qs, deploy_jo consolidated_config_set = "\n".join(plans_to_deploy.values_list("config_set", flat=True)) logger.debug(f"Consolidated config set: {consolidated_config_set}") # TODO: Future: We should add post-processing rendering here - # after https://github.com/nautobot/nautobot-plugin-golden-config/issues/443 + # after https://github.com/nautobot/nautobot-app-golden-config/issues/443 plans_to_deploy.update(status=Status.objects.get(name="In Progress")) try: diff --git a/nautobot_golden_config/nornir_plays/config_intended.py b/nautobot_golden_config/nornir_plays/config_intended.py index ea5c2692..d326b206 100644 --- a/nautobot_golden_config/nornir_plays/config_intended.py +++ b/nautobot_golden_config/nornir_plays/config_intended.py @@ -46,7 +46,7 @@ def run_template( # pylint: disable=too-many-arguments,too-many-locals Args: task (Task): Nornir task individual object logger (NornirLogger): Logger to log messages to. - global_settings (GoldenConfigSetting): The settings for GoldenConfigPlugin. + global_settings (GoldenConfigSetting): The settings for GoldenConfigApp. job_class_instance (Result): The the output from the Nautobot Job instance being run. Returns: diff --git a/nautobot_golden_config/tables.py b/nautobot_golden_config/tables.py index abf89480..9031c6d1 100644 --- a/nautobot_golden_config/tables.py +++ b/nautobot_golden_config/tables.py @@ -1,4 +1,4 @@ -"""Django Tables2 classes for golden_config plugin.""" +"""Django Tables2 classes for golden_config app.""" import copy from django.utils.html import format_html diff --git a/nautobot_golden_config/template_content.py b/nautobot_golden_config/template_content.py index b43029c3..04f71628 100644 --- a/nautobot_golden_config/template_content.py +++ b/nautobot_golden_config/template_content.py @@ -8,7 +8,7 @@ class ConfigComplianceDeviceCheck(PluginTemplateExtension): # pylint: disable=abstract-method - """Plugin extension class for config compliance.""" + """App extension class for config compliance.""" model = "dcim.device" @@ -48,7 +48,7 @@ def detail_tabs(self): class ConfigComplianceLocationCheck(PluginTemplateExtension): # pylint: disable=abstract-method - """Plugin extension class for config compliance.""" + """App extension class for config compliance.""" model = "dcim.location" @@ -82,7 +82,7 @@ def right_page(self): class ConfigDeviceDetails(PluginTemplateExtension): # pylint: disable=abstract-method - """Plugin extension class for config compliance.""" + """App extension class for config compliance.""" model = "dcim.device" @@ -109,7 +109,7 @@ def right_page(self): class ConfigComplianceTenantCheck(PluginTemplateExtension): # pylint: disable=abstract-method - """Plugin extension class for config compliance.""" + """App extension class for config compliance.""" model = "tenancy.tenant" diff --git a/nautobot_golden_config/tests/__init__.py b/nautobot_golden_config/tests/__init__.py index 490aab85..6680c4dc 100644 --- a/nautobot_golden_config/tests/__init__.py +++ b/nautobot_golden_config/tests/__init__.py @@ -1 +1 @@ -"""Unit tests for nautobot_golden_config plugin.""" +"""Unit tests for nautobot_golden_config app.""" diff --git a/nautobot_golden_config/tests/test_graphql.py b/nautobot_golden_config/tests/test_graphql.py index ed1bc897..386f0756 100644 --- a/nautobot_golden_config/tests/test_graphql.py +++ b/nautobot_golden_config/tests/test_graphql.py @@ -1,4 +1,4 @@ -"""Golden Configuration Plugin GraphQL Testing.""" +"""Golden Configuration App GraphQL Testing.""" import uuid @@ -69,7 +69,7 @@ class TestGraphQLQuery(TestCase): # pylint: disable=too-many-instance-attributes - """Test GraphQL Queries for Golden Config Plugin.""" + """Test GraphQL Queries for Golden Config app.""" def setUp(self): """Setup request and create test data to validate GraphQL.""" diff --git a/nautobot_golden_config/tests/test_models.py b/nautobot_golden_config/tests/test_models.py index e22fc246..28ada425 100644 --- a/nautobot_golden_config/tests/test_models.py +++ b/nautobot_golden_config/tests/test_models.py @@ -151,7 +151,7 @@ def test_absolute_url_success(self): self.assertIn(f"/plugins/golden-config/golden-config-setting/{self.global_settings.pk}", url_string) def test_good_graphql_query_invalid_starts_with(self): - """Valid graphql query, however invalid in the usage with golden config plugin.""" + """Valid graphql query, however invalid in the usage with golden config app.""" self.global_settings.sot_agg_query = GraphQLQuery.objects.get(name="GC-SoTAgg-Query-3") with self.assertRaises(ValidationError) as error: self.global_settings.clean() diff --git a/nautobot_golden_config/tests/test_views.py b/nautobot_golden_config/tests/test_views.py index 7a6f9570..b5debfb3 100644 --- a/nautobot_golden_config/tests/test_views.py +++ b/nautobot_golden_config/tests/test_views.py @@ -179,12 +179,13 @@ def setUp(self): self.gc_dynamic_group = self.gc_settings.dynamic_group self.gc_dynamic_group.filter = {"name": [dev.name for dev in Device.objects.all()]} self.gc_dynamic_group.validated_save() + models.GoldenConfig.objects.create(device=Device.objects.first()) - def _get_golden_config_table(self): + def _get_golden_config_table_header(self): response = self.client.get(f"{self._url}") html_parsed = html.fromstring(response.content.decode()) golden_config_table = html_parsed.find_class("table")[0] - return golden_config_table.iterchildren() + return golden_config_table.find("thead") @property def _text_table_headers(self): @@ -199,7 +200,7 @@ def test_page_ok(self): self.assertEqual(response.status_code, 200) def test_headers_in_table(self): - table_header, _ = self._get_golden_config_table() + table_header = self._get_golden_config_table_header() headers = table_header.iterdescendants("th") checkbox_header = next(headers) checkbox_element = checkbox_header.find("input") @@ -225,7 +226,7 @@ def test_device_relationship_not_included_in_golden_config_table(self): destination_id=device.id, relationship_id=relationship.id, ) - table_header, _ = self._get_golden_config_table() + table_header = self._get_golden_config_table_header() # xpath expression excludes the pk checkbox column (i.e. the first column) text_headers = [header.text_content() for header in table_header.xpath("tr/th[position()>1]")] # This will fail if the Relationships to Device objects showed up in the Golden Config table diff --git a/nautobot_golden_config/urls.py b/nautobot_golden_config/urls.py index 2bd38845..24e238b7 100644 --- a/nautobot_golden_config/urls.py +++ b/nautobot_golden_config/urls.py @@ -1,4 +1,4 @@ -"""Django urlpatterns declaration for config compliance plugin.""" +"""Django urlpatterns declaration for config compliance app.""" from django.urls import path from nautobot.core.views.routers import NautobotUIViewSetRouter diff --git a/nautobot_golden_config/utilities/config_postprocessing.py b/nautobot_golden_config/utilities/config_postprocessing.py index 9df3ccbb..2e6a7597 100644 --- a/nautobot_golden_config/utilities/config_postprocessing.py +++ b/nautobot_golden_config/utilities/config_postprocessing.py @@ -131,9 +131,7 @@ def get_config_postprocessing(configs: models.GoldenConfig, request: HttpRequest request (HttpRequest): HTTP request for context. """ if not ENABLE_POSTPROCESSING: - return ( - "Generation of intended configurations postprocessing it is not enabled, check your plugin configuration." - ) + return "Generation of intended configurations postprocessing it is not enabled, check your app configuration." config_postprocessing = configs.intended_config if not config_postprocessing: @@ -166,7 +164,7 @@ def get_config_postprocessing(configs: models.GoldenConfig, request: HttpRequest msg = ( "There was an issue attempting to import a `postprocessing_callables` function of " f"{func_name_subscribed}, this is expected with a local configuration issue and not related to" - " the Golden Configuration Plugin, please contact your system admin for further details.\n" + " the Golden Configuration App, please contact your system admin for further details.\n" ) raise ValueError(msg + str(error)) from error else: diff --git a/nautobot_golden_config/views.py b/nautobot_golden_config/views.py index 633ba910..ad1f601e 100644 --- a/nautobot_golden_config/views.py +++ b/nautobot_golden_config/views.py @@ -363,7 +363,7 @@ class ConfigComplianceOverview(generic.ObjectListView): extra_content = {} # Once https://github.com/nautobot/nautobot/issues/4529 is addressed, can turn this on. - # Permalink reference: https://github.com/nautobot/nautobot-plugin-golden-config/blob/017d5e1526fa9f642b9e02bfc7161f27d4948bef/nautobot_golden_config/views.py#L383 + # Permalink reference: https://github.com/nautobot/nautobot-app-golden-config/blob/017d5e1526fa9f642b9e02bfc7161f27d4948bef/nautobot_golden_config/views.py#L383 # @action(detail=False, methods=["get"]) # def overview(self, request, *args, **kwargs): def setup(self, request, *args, **kwargs): @@ -566,7 +566,7 @@ def get_required_permission(self): return "extras.run_job" # Once https://github.com/nautobot/nautobot/issues/4529 is addressed, can turn this on. - # Permalink reference: https://github.com/nautobot/nautobot-plugin-golden-config/blob/017d5e1526fa9f642b9e02bfc7161f27d4948bef/nautobot_golden_config/views.py#L609-L612 + # Permalink reference: https://github.com/nautobot/nautobot-app-golden-config/blob/017d5e1526fa9f642b9e02bfc7161f27d4948bef/nautobot_golden_config/views.py#L609-L612 # @action(detail=False, methods=["post"]) # def bulk_deploy(self, request): def post(self, request): diff --git a/pyproject.toml b/pyproject.toml index 7dfece0a..8ae39f41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,14 +1,14 @@ [tool.poetry] name = "nautobot-golden-config" version = "2.0.0" -description = "A plugin for configuration on nautobot" +description = "An app for configuration on nautobot" authors = ["Network to Code, LLC "] license = "Apache-2.0" readme = "README.md" homepage = "https://docs.nautobot.com/projects/golden-config/en/latest/" -repository = "https://github.com/nautobot/nautobot-plugin-golden-config" +repository = "https://github.com/nautobot/nautobot-app-golden-config" documentation = "https://docs.nautobot.com/projects/golden-config/en/latest/" -keywords = ["nautobot", "nautobot-plugin"] +keywords = ["nautobot", "nautobot-plugin", "nautobot-app"] classifiers = [ "Intended Audience :: Developers", "Development Status :: 5 - Production/Stable", @@ -28,7 +28,7 @@ packages = [ [tool.poetry.urls] "Changelog" = "https://docs.nautobot.com/projects/golden-config/en/latest/admin/release_notes/" -"Bug Tracker" = "https://github.com/nautobot/nautobot-plugin-golden-config/issues" +"Bug Tracker" = "https://github.com/nautobot/nautobot-app-golden-config/issues" [tool.poetry.dependencies] python = ">=3.8,<3.12" diff --git a/tasks.py b/tasks.py index acad3324..ae27bdca 100644 --- a/tasks.py +++ b/tasks.py @@ -669,7 +669,7 @@ def unittest_coverage(context): } ) def tests(context, failfast=False, keepdb=False, lint_only=False): - """Run all tests for this plugin.""" + """Run all tests for this app.""" # If we are not running locally, start the docker containers so we don't have to for each test if not is_truthy(context.nautobot_golden_config.local): print("Starting Docker Containers...") From a75b9951985171b8daa41df40f5f681d3b136e52 Mon Sep 17 00:00:00 2001 From: Steven W <111259311+DistantVoyager@users.noreply.github.com> Date: Tue, 9 Jan 2024 09:11:34 -0500 Subject: [PATCH 02/17] Fixed help text typo (#693) Co-authored-by: Ken Celenza --- nautobot_golden_config/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_golden_config/models.py b/nautobot_golden_config/models.py index 62023a74..e9ccd9b6 100644 --- a/nautobot_golden_config/models.py +++ b/nautobot_golden_config/models.py @@ -488,7 +488,7 @@ class GoldenConfigSetting(PrimaryModel): # pylint: disable=too-many-ancestors max_length=255, blank=True, verbose_name="Intended Path in Jinja Template Form", - help_text="The Jinja path representation of where the generated file will be places. e.g. `{{obj.location.name|slugify}}/{{obj.name}}.cfg`", + help_text="The Jinja path representation of where the generated file will be placed. e.g. `{{obj.location.name|slugify}}/{{obj.name}}.cfg`", ) jinja_repository = models.ForeignKey( to="extras.GitRepository", From 74a72ffa0f603b973aca1fcd659f3f71e671ad09 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Sat, 20 Jan 2024 14:56:59 -0500 Subject: [PATCH 03/17] Closes: #699 - Remove stale reference to `platform_slug_map` (#700) * Closes: #699 - Remove stale reference to * Closes #701 - Old URL patterns in README.md --- .github/workflows/ci.yml | 19 +++++++++++++++++++ README.md | 6 +++--- docs/admin/install.md | 5 ++--- docs/admin/migrating_to_v2.md | 2 +- .../utilities/config_postprocessing.py | 2 +- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6a29728..ba1e7834 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,17 @@ jobs: uses: "networktocode/gh-action-setup-poetry-environment@v4" - name: "Linting: flake8" run: "poetry run invoke flake8" + check-docs-build: + runs-on: "ubuntu-22.04" + env: + INVOKE_NAUTOBOT_GOLDEN_CONFIG_LOCAL: "True" + steps: + - name: "Check out repository code" + uses: "actions/checkout@v4" + - name: "Setup environment" + uses: "networktocode/gh-action-setup-poetry-environment@v4" + - name: "Check Docs Build" + run: "poetry run invoke build-and-check-docs" poetry: runs-on: "ubuntu-22.04" env: @@ -238,6 +249,10 @@ jobs: 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 --no-root" + - name: "Build Documentation" + run: "poetry run invoke build-and-check-docs" - name: "Run Poetry Build" run: "poetry build" - name: "Upload binaries to release" @@ -267,6 +282,10 @@ jobs: 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 --no-root" + - name: "Build Documentation" + run: "poetry run invoke build-and-check-docs" - name: "Run Poetry Build" run: "poetry build" - name: "Push to PyPI" diff --git a/README.md b/README.md index 3c74b687..c18a4e58 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ This App is installed in the Nautobot Community Sandbox found over at [demo.naut Full web-based HTML documentation for this app can be found over on the [Nautobot Docs](https://docs.nautobot.com/projects/golden-config/en/latest/) website: - [User Guide](https://docs.nautobot.com/projects/golden-config/en/latest/user/app_overview/) - Overview, Using the App, Getting Started, Navigating compliance (cli, json, custom), backup, app usage, intended state creation. -- [Administrator Guide](https://docs.nautobot.com/projects/golden-config/en/latest/admin/admin_install/) - How to Install, Configure, Upgrade, or Uninstall the App. -- [Developer Guide](https://docs.nautobot.com/projects/golden-config/en/latest/dev/dev_contributing/) - Extending the App, Code Reference, Contribution Guide. +- [Administrator Guide](https://docs.nautobot.com/projects/golden-config/en/latest/admin/install/) - How to Install, Configure, Upgrade, or Uninstall the App. +- [Developer Guide](https://docs.nautobot.com/projects/golden-config/en/latest/dev/contributing/) - Extending the App, Code Reference, Contribution Guide. - [Release Notes / Changelog](https://docs.nautobot.com/projects/golden-config/en/latest/admin/release_notes/) -- [Frequently Asked Questions](https://docs.nautobot.com/projects/golden-config/en/latest/user/app_faq/) +- [Frequently Asked Questions](https://docs.nautobot.com/projects/golden-config/en/latest/user/faq/) ### Contributing to the Docs diff --git a/docs/admin/install.md b/docs/admin/install.md index ca1dec70..9a818399 100644 --- a/docs/admin/install.md +++ b/docs/admin/install.md @@ -109,7 +109,6 @@ The app behavior can be controlled with the following list of settings: | default_deploy_status | "Not Approved" | "Not Approved" | A string that will be the name of the status you want as the default when create new config plans, you MUST create the status yourself before starting the app. | | postprocessing_callables | ['mypackage.myfunction'] | [] | A list of function paths, in dotted format, that are appended to the available methods for post-processing the intended configuration, for instance, the `render_secrets`. | | postprocessing_subscribed | ['mypackage.myfunction'] | [] | A list of function paths, that should exist as postprocessing_callables, that defines the order of application of during the post-processing process. | -| 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 within `netutils.config.compliance.parser_map`. | | sot_agg_transposer | "mypkg.transposer" | None | A string representation of a function that can post-process the graphQL data. | | per_feature_bar_width | 0.15 | 0.15 | The width of the table bar within the overview report | | per_feature_width | 13 | 13 | The width in inches that the overview table can be. | @@ -117,10 +116,10 @@ The app behavior can be controlled with the following list of settings: | jinja_env | {"lstrip_blocks": False} | See Note Below | A dictionary of Jinja2 Environment options compatible with Jinja2.SandboxEnvironment() | !!! note - Over time the compliance report will become more dynamic, but for now allow users to configure the `per_*` configs in a way that fits best for them. + `platform_slug_map` configuration was removed as of the `v2.0.0` release of Golden Config, for more information please review the [v2 Migration Guide](./migrating_to_v2.md) !!! note - Review [`nautobot_plugin_nornir`](https://docs.nautobot.com/projects/plugin-nornir/en/latest/user/app_feature_dispatcher/) for Nornir and dispatcher configuration options. + Over time the compliance report will become more dynamic, but for now allow users to configure the `per_*` configs in a way that fits best for them. !!! note Defaults for Jinja2 environment settings (`jinja_env`) are as follows: diff --git a/docs/admin/migrating_to_v2.md b/docs/admin/migrating_to_v2.md index e1452cfb..f074aa7f 100644 --- a/docs/admin/migrating_to_v2.md +++ b/docs/admin/migrating_to_v2.md @@ -43,7 +43,7 @@ If previously you have leveraged the `dispatcher_mapping` to use your preferred !!! tip You can safely skip this section if your Dynamic Groups was not using slugs/Site/Region/DeviceRole or your Dynamic Groups are currently in the required state. -In an effort to guide you along, you are highly encouraged to leverage the `nautobot-server audit_dynamic_groups` as [documented](https://docs.nautobot.com/projects/core/en/v2.0.0/user-guide/administration/tools/nautobot-server/#audit_dynamic_groups). You will know you have completed this step, when the scope of devices in your Dynamic Group match your expectations. +In an effort to guide you along, you are highly encouraged to leverage the `nautobot-server audit_dynamic_groups` as [documented](https://docs.nautobot.com/projects/core/en/stable/user-guide/administration/tools/nautobot-server/#audit_dynamic_groups). You will know you have completed this step, when the scope of devices in your Dynamic Group match your expectations. ## GraphQL diff --git a/nautobot_golden_config/utilities/config_postprocessing.py b/nautobot_golden_config/utilities/config_postprocessing.py index 2e6a7597..4254f882 100644 --- a/nautobot_golden_config/utilities/config_postprocessing.py +++ b/nautobot_golden_config/utilities/config_postprocessing.py @@ -78,7 +78,7 @@ def render_secrets(config_postprocessing: str, configs: models.GoldenConfig, req if not config_postprocessing: return "" - # Based on https://docs.nautobot.com/projects/golden-config/en/latest/dev/dev_adr/#renders-secrets + # Based on https://docs.nautobot.com/projects/golden-config/en/latest/user/app_feature_config_postprocessing/?h=secrets#render-secrets # the Jinja2 environment that starts with Nautobot should not be used. jinja_env = SandboxedEnvironment(autoescape=True) From 54d282939dfb12908c51c47ba0ed617957e0d694 Mon Sep 17 00:00:00 2001 From: Ken Celenza Date: Sat, 20 Jan 2024 15:21:33 -0500 Subject: [PATCH 04/17] Update faq link on readme (#702) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c18a4e58..4558268f 100644 --- a/README.md +++ b/README.md @@ -78,4 +78,4 @@ Any PRs with fixes or improvements are very welcome! ## Questions -For any questions or comments, please check the [FAQ](https://docs.nautobot.com/projects/golden-config/en/latest/user/app_faq/) first. Feel free to also swing by the [Network to Code Slack](https://networktocode.slack.com/) (channel `#nautobot`), sign up [here](http://slack.networktocode.com/) if you don't have an account. +For any questions or comments, please check the [FAQ](https://docs.nautobot.com/projects/golden-config/en/latest/user/faq/) first. Feel free to also swing by the [Network to Code Slack](https://networktocode.slack.com/) (channel `#nautobot`), sign up [here](http://slack.networktocode.com/) if you don't have an account. From ec8ffebec07b9b30f54fde3e4dc844022a9e3874 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Fri, 9 Feb 2024 12:11:40 -0500 Subject: [PATCH 05/17] missing reference for status (#719) --- .../configplan_create.html | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/nautobot_golden_config/templates/nautobot_golden_config/configplan_create.html b/nautobot_golden_config/templates/nautobot_golden_config/configplan_create.html index c7661d40..e7aecf8c 100644 --- a/nautobot_golden_config/templates/nautobot_golden_config/configplan_create.html +++ b/nautobot_golden_config/templates/nautobot_golden_config/configplan_create.html @@ -57,7 +57,22 @@ setupFieldListeners(hideFormData) function formatJobData(data) { - var arrayFields = ["feature", "device_type", "tenant_group", "tenant","location", "rack_group","rack","role","manufacturer","platform","device_type","device","tags"] + var arrayFields = [ + "feature", + "device_type", + "tenant_group", + "tenant", + "location", + "rack_group", + "rack", + "role", + "manufacturer", + "platform", + "device_type", + "device", + "tags", + "status" + ] var form_data = formDataToDictionary(data, arrayFields); delete form_data.csrfmiddlewaretoken; delete form_data.q; From 4de3f3778596bfac6ab2318373b0d8aee2323bcf Mon Sep 17 00:00:00 2001 From: Allen Hogan <98360253+alhogan@users.noreply.github.com> Date: Thu, 15 Feb 2024 09:06:23 -0600 Subject: [PATCH 06/17] added decorator to close db connections for threaded tasks (#715) --- nautobot_golden_config/nornir_plays/config_deployment.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nautobot_golden_config/nornir_plays/config_deployment.py b/nautobot_golden_config/nornir_plays/config_deployment.py index b59502fd..2dc98b69 100644 --- a/nautobot_golden_config/nornir_plays/config_deployment.py +++ b/nautobot_golden_config/nornir_plays/config_deployment.py @@ -1,4 +1,5 @@ """Nornir job for deploying configurations.""" + from datetime import datetime import logging @@ -21,13 +22,13 @@ from nautobot_golden_config.nornir_plays.processor import ProcessGoldenConfig from nautobot_golden_config.utilities.helper import dispatch_params from nautobot_golden_config.utilities.logger import NornirLogger - - +from nautobot_golden_config.utilities.db_management import close_threaded_db_connections from nautobot_golden_config.utilities.constant import DEFAULT_DEPLOY_STATUS InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory) +@close_threaded_db_connections def run_deployment(task: Task, logger: logging.Logger, config_plan_qs, deploy_job_result) -> Result: """Deploy configurations to device.""" obj = task.host.data["obj"] From 8bd121d9a263ea4e2c1f9cbd1168c58ba2a81e01 Mon Sep 17 00:00:00 2001 From: Jeff Kala <48843785+jeffkala@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:16:36 -0700 Subject: [PATCH 07/17] implement objectchange log excludes for object_data_v2 data as well (#726) --- nautobot_golden_config/models.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/nautobot_golden_config/models.py b/nautobot_golden_config/models.py index e9ccd9b6..a9239427 100644 --- a/nautobot_golden_config/models.py +++ b/nautobot_golden_config/models.py @@ -314,14 +314,18 @@ def to_objectchange( self, action, *, related_object=None, object_data_extra=None, object_data_exclude=None ): # pylint: disable=arguments-differ """Remove actual and intended configuration from changelog.""" + fields_to_exclude = ["actual", "intended"] if not object_data_exclude: - object_data_exclude = ["actual", "intended"] + object_data_exclude = fields_to_exclude + data_v2 = serialize_object_v2(self) + for field in fields_to_exclude: + data_v2.pop(field) return ObjectChange( changed_object=self, object_repr=str(self), action=action, object_data=serialize_object(self, extra=object_data_extra, exclude=object_data_exclude), - object_data_v2=serialize_object_v2(self), + object_data_v2=data_v2, related_object=related_object, ) @@ -413,14 +417,18 @@ def to_objectchange( self, action, *, related_object=None, object_data_extra=None, object_data_exclude=None ): # pylint: disable=arguments-differ """Remove actual and intended configuration from changelog.""" + fields_to_exclude = ["backup_config", "intended_config", "compliance_config"] if not object_data_exclude: - object_data_exclude = ["backup_config", "intended_config", "compliance_config"] + object_data_exclude = fields_to_exclude + data_v2 = serialize_object_v2(self) + for field in fields_to_exclude: + data_v2.pop(field) return ObjectChange( changed_object=self, object_repr=str(self), action=action, object_data=serialize_object(self, extra=object_data_extra, exclude=object_data_exclude), - object_data_v2=serialize_object_v2(self), + object_data_v2=data_v2, related_object=related_object, ) From 4de2396c98b17ec42c9adac2e2805b5a5b6701a7 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Sat, 24 Feb 2024 00:18:15 -0500 Subject: [PATCH 08/17] adding logic to handle jobs requiring approvals (#718) * adding logic to handle jobs requiring approvals * typo * Update run_job.js --------- Co-authored-by: Ken Celenza --- nautobot_golden_config/static/run_job.js | 271 ++++++++++++----------- 1 file changed, 144 insertions(+), 127 deletions(-) diff --git a/nautobot_golden_config/static/run_job.js b/nautobot_golden_config/static/run_job.js index 938f4920..de978300 100644 --- a/nautobot_golden_config/static/run_job.js +++ b/nautobot_golden_config/static/run_job.js @@ -9,49 +9,66 @@ * @param {string} callBack - The promise function to return the success or failure message, leave `undefined` no callback is required. */ function startJob(jobClass, data, redirectUrlTemplate, callBack) { - var jobApi = `/api/extras/jobs/${jobClass}/run/`; + var jobApi = `/api/extras/jobs/${jobClass}/run/`; - if (typeof callBack === "undefined") { - var callBack = getMessage; - } + if (typeof callBack === "undefined") { + var callBack = getMessage; + } - $.ajax({ - type: 'POST', - url: jobApi, - contentType: "application/json", - data: JSON.stringify(data), - dataType: 'json', - headers: { - 'X-CSRFToken': nautobot_csrf_token - }, - beforeSend: function() { - // Normalize to base as much as you can. - $('#jobStatus').html("Pending").show(); - $('#loaderImg').show(); - $('#jobResults').hide(); - $('#redirectLink').hide(); - $('#detailMessages').hide(); - }, - success: function(jobData) { - $('#jobStatus').html("Started").show(); - var jobResultUrl = "/extras/job-results/" + jobData.job_result.id + "/"; - $('#jobResults').html(iconLink(jobResultUrl, "mdi-open-in-new", "Job Details")).show(); - pollJobStatus(jobData.job_result.url, callBack); - if (typeof redirectUrlTemplate !== "undefined") { - var redirectUrl = _renderTemplate(redirectUrlTemplate, jobData); - $('#redirectLink').html(iconLink(redirectUrl, "mdi-open-in-new", "Info")); - } - }, - error: function(e) { - $("#loaderImg").hide(); - console.log("There was an error with your request..."); - console.log("error: " + JSON.stringify(e)); - $('#jobStatus').html("Failed").show(); - $('#detailMessages').show(); - $('#detailMessages').attr('class', 'alert alert-danger text-center'); - $('#detailMessages').html("Error: " + e.responseText); - } - }); + $.ajax({ + type: 'POST', + url: jobApi, + contentType: "application/json", + data: JSON.stringify(data), + dataType: 'json', + headers: { + 'X-CSRFToken': nautobot_csrf_token + }, + beforeSend: function () { + // Normalize to base as much as you can. + $('#jobStatus').html("Pending").show(); + $('#loaderImg').show(); + $('#jobResults').hide(); + $('#redirectLink').hide(); + $('#detailMessages').hide(); + }, + success: function (jobData) { + if (jobData.job_result) { + // if you get a 200 response and job_result data is there, you know it was a good run + $('#jobStatus').html("Started").show(); + var jobResultUrl = "/extras/job-results/" + jobData.job_result.id + "/"; + $('#jobResults').html(iconLink(jobResultUrl, "mdi-open-in-new", "Job Details")).show(); + pollJobStatus(jobData.job_result.url, callBack); + if (typeof redirectUrlTemplate !== "undefined") { + var redirectUrl = _renderTemplate(redirectUrlTemplate, jobData); + $('#redirectLink').html(iconLink(redirectUrl, "mdi-open-in-new", "Info")); + } + } else if (jobData.scheduled_job && jobData.scheduled_job.approval_required) { + // Job approvals have this relevant data structure { "scheduled_job": {"approval_required": true }} + $("#loaderImg").hide(); + $('#jobStatus').html("Pending Approval").show(); + $('#detailMessages').show(); + $('#detailMessages').html(`

Job is pending approval, please review Job Approval

`); + } else { + // Response was 200 but did not return a job_result OR a scheduled_job pending approval, this condition should not be possible at the time of development but was added to prevent the modal going into a hung state + $("#loaderImg").hide(); + $('#jobStatus').html("Unknown").show(); + $('#detailMessages').show(); + $('#detailMessages').attr('class', 'alert alert-danger text-center'); + $('#detailMessages').html("

The call to launch the job was successful but an unknown error has occurred, response has been logged to the browser console.

"); + console.log("error: " + JSON.stringify(jobData)); + } + }, + error: function (e) { + $("#loaderImg").hide(); + console.log("There was an error with your request..."); + console.log("error: " + JSON.stringify(e)); + $('#jobStatus').html("Failed").show(); + $('#detailMessages').show(); + $('#detailMessages').attr('class', 'alert alert-danger text-center'); + $('#detailMessages').html("Error: " + e.responseText); + } + }); } /** @@ -70,50 +87,50 @@ function startJob(jobClass, data, redirectUrlTemplate, callBack) { * @returns {void} */ function pollJobStatus(jobId, callBack) { - $.ajax({ - url: jobId, - type: "GET", - async: false, - dataType: "json", - headers: { - 'X-CSRFToken': nautobot_csrf_token - }, - success: function(data) { - $('#jobStatus').html(data.status.value.charAt(0).toUpperCase() + data.status.value.slice(1)).show(); - if (["FAILURE", "REVOKED"].includes(data.status.value)) { - $("#loaderImg").hide(); - $('#detailMessages').show(); - $('#detailMessages').attr('class', 'alert alert-warning text-center'); - $('#detailMessages').html("Job started but failed during the Job run. This job may have partially completed. See Job Results for more details on the errors."); - } else if (["PENDING", "RECEIVED", "RETRY", "STARTED"].includes(data.status.value)) { - // Job is still processing, continue polling - setTimeout(function() { - pollJobStatus(jobId, callBack); - }, 1000); // Poll every 1 seconds - } else if (["SUCCESS"].includes(data.status.value)) { - $("#loaderImg").hide(); - $('#detailMessages').show(); - callBack(data.id) - .then((message) => { - $('#redirectLink').show(); - $('#detailMessages').attr('class', 'alert alert-success text-center'); - $('#detailMessages').html(message) - }) - .catch((message) => { - $('#detailMessages').attr('class', 'alert alert-warning text-center'); - $('#detailMessages').html(message) - }) - } - }, - error: function(e) { - $("#loaderImg").hide(); - console.log("There was an error with your request..."); - console.log("error: " + JSON.stringify(e)); - $('#detailMessages').show(); - $('#detailMessages').attr('class', 'alert alert-danger text-center'); - $('#detailMessages').html("Error: " + e.responseText); - } - }) + $.ajax({ + url: jobId, + type: "GET", + async: false, + dataType: "json", + headers: { + 'X-CSRFToken': nautobot_csrf_token + }, + success: function (data) { + $('#jobStatus').html(data.status.value.charAt(0).toUpperCase() + data.status.value.slice(1)).show(); + if (["FAILURE", "REVOKED"].includes(data.status.value)) { + $("#loaderImg").hide(); + $('#detailMessages').show(); + $('#detailMessages').attr('class', 'alert alert-warning text-center'); + $('#detailMessages').html("Job started but failed during the Job run. This job may have partially completed. See Job Results for more details on the errors."); + } else if (["PENDING", "RECEIVED", "RETRY", "STARTED"].includes(data.status.value)) { + // Job is still processing, continue polling + setTimeout(function () { + pollJobStatus(jobId, callBack); + }, 1000); // Poll every 1 seconds + } else if (["SUCCESS"].includes(data.status.value)) { + $("#loaderImg").hide(); + $('#detailMessages').show(); + callBack(data.id) + .then((message) => { + $('#redirectLink').show(); + $('#detailMessages').attr('class', 'alert alert-success text-center'); + $('#detailMessages').html(message) + }) + .catch((message) => { + $('#detailMessages').attr('class', 'alert alert-warning text-center'); + $('#detailMessages').html(message) + }) + } + }, + error: function (e) { + $("#loaderImg").hide(); + console.log("There was an error with your request..."); + console.log("error: " + JSON.stringify(e)); + $('#detailMessages').show(); + $('#detailMessages').attr('class', 'alert alert-danger text-center'); + $('#detailMessages').html("Error: " + e.responseText); + } + }) }; /** * Converts a list of form data objects to a dictionary. @@ -123,25 +140,25 @@ function pollJobStatus(jobId, callBack) { * @returns {Object} - The dictionary representation of the form data. */ function formDataToDictionary(formData, listKeys) { - const dict = {}; + const dict = {}; - formData.forEach(item => { - const { - name, - value - } = item; - if (listKeys.includes(name)) { - if (!dict[name]) { - dict[name] = [value]; - } else { - dict[name].push(value); - } - } else { - dict[name] = value; - } - }); + formData.forEach(item => { + const { + name, + value + } = item; + if (listKeys.includes(name)) { + if (!dict[name]) { + dict[name] = [value]; + } else { + dict[name].push(value); + } + } else { + dict[name] = value; + } + }); - return dict; + return dict; } /** @@ -154,12 +171,12 @@ function formDataToDictionary(formData, listKeys) { */ function iconLink(url, icon, title) { - const linkUrl = `` + - ` ` + - ` ` + - ` ` + - `` - return linkUrl + const linkUrl = `` + + ` ` + + ` ` + + ` ` + + `` + return linkUrl } /** @@ -170,28 +187,28 @@ function iconLink(url, icon, title) { * @returns {string} - The rendered string with placeholders replaced by actual values from jobData. */ function _renderTemplate(templateString, data) { - // Create a regular expression to match placeholders in the template - const placeholderRegex = /\{jobData\.([^\}]+)\}/g; + // Create a regular expression to match placeholders in the template + const placeholderRegex = /\{jobData\.([^\}]+)\}/g; - // Replace placeholders with corresponding values from jobData - const renderedString = templateString.replace(placeholderRegex, (match, key) => { - const keys = key.split("."); - let value = data; - for (const k of keys) { - if (value.hasOwnProperty(k)) { - value = value[k]; - } else { - return match; // If the key is not found, keep the original placeholder - } - } - return value; - }); + // Replace placeholders with corresponding values from jobData + const renderedString = templateString.replace(placeholderRegex, (match, key) => { + const keys = key.split("."); + let value = data; + for (const k of keys) { + if (value.hasOwnProperty(k)) { + value = value[k]; + } else { + return match; // If the key is not found, keep the original placeholder + } + } + return value; + }); - return renderedString; + return renderedString; } function getMessage(jobResultId) { - return new Promise((resolve) => { - resolve("Job Completed Successfully."); - }); + return new Promise((resolve) => { + resolve("Job Completed Successfully."); + }); } \ No newline at end of file From 566c1ccde2ba088805b8140a2a6b9a47c3c0dfe7 Mon Sep 17 00:00:00 2001 From: Nautobot-Bot <79372327+nautobot-bot@users.noreply.github.com> Date: Wed, 28 Feb 2024 18:22:53 -0600 Subject: [PATCH 09/17] Cookie updated by NetworkToCode Cookie Drift Manager Tool (#707) * Cookie updated by NetworkToCode Cookie Drift Manager Tool Template: ``` { "template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "dir": "nautobot-app", "ref": "refs/tags/nautobot-app-v2.1.0", "path": null } ``` Cookie: ``` { "remote": "https://github.com/nautobot/nautobot-app-golden-config.git", "path": "/tmp/tmp1woi9xuq/nautobot-app-golden-config", "repository_path": "/tmp/tmp1woi9xuq/nautobot-app-golden-config", "dir": "", "branch_prefix": "drift-manager", "context": { "codeowner_github_usernames": "@itdependsnetworks @jeffkala @nkallergis", "full_name": "Network to Code, LLC", "email": "opensource@networktocode.com", "github_org": "nautobot", "app_name": "nautobot_golden_config", "verbose_name": "Golden Config", "app_slug": "nautobot-golden-config", "project_slug": "nautobot-app-golden-config", "repo_url": "https://github.com/nautobot/nautobot-app-golden-config", "base_url": "golden-config", "min_nautobot_version": "2.0.0", "max_nautobot_version": "2.9999", "camel_name": "NautobotGoldenConfig", "project_short_description": "An app for configuration on nautobot", "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/golden-config/en/latest", "_template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "_output_dir": "/tmp/tmp1woi9xuq", "_repo_dir": "/github/home/.cookiecutters/cookiecutter-nautobot-app/nautobot-app", "_checkout": "refs/tags/nautobot-app-v2.1.0" }, "base_branch": "develop", "remote_name": "origin", "pull_request_strategy": "PullRequestStrategy.CREATE", "post_actions": [ "PostAction.BLACK" ], "baked_commit_ref": "c6963e367d835faf66a9f4ac63267b6ce5811577", "draft": true } ``` CLI Arguments: ``` { "cookie_dir": "", "input": false, "json_filename": "", "output_dir": "", "push": true, "template": "", "template_dir": "", "template_ref": "refs/tags/nautobot-app-v2.1.0", "pull_request": null, "post_action": [], "disable_post_actions": false, "draft": null } ``` Co-authored-by: bakebot Co-authored-by: Jan Snasel --- .cookiecutter.json | 4 +- .../pull_request_template.md | 2 +- .github/workflows/ci.yml | 50 ++++-- .github/workflows/rebake.yml | 118 -------------- LICENSE | 2 +- README.md | 2 +- changes/.gitignore | 1 + changes/707.changed | 1 + development/Dockerfile | 4 +- development/docker-compose.base.yml | 6 +- development/docker-compose.dev.yml | 12 ++ development/nautobot_config.py | 3 - development/towncrier_template.j2 | 30 ++++ docs/admin/uninstall.md | 6 + docs/assets/extra.css | 5 + docs/dev/contributing.md | 31 +++- docs/dev/dev_environment.md | 7 +- nautobot_golden_config/__init__.py | 7 +- .../nornir_plays/__init__.py | 1 + poetry.lock | 115 +++++++++---- pyproject.toml | 127 ++++++++++++--- tasks.py | 153 +++++++++++++++--- 22 files changed, 460 insertions(+), 227 deletions(-) delete mode 100644 .github/workflows/rebake.yml create mode 100644 changes/.gitignore create mode 100644 changes/707.changed create mode 100644 development/towncrier_template.j2 diff --git a/.cookiecutter.json b/.cookiecutter.json index a18290bd..b19002e0 100644 --- a/.cookiecutter.json +++ b/.cookiecutter.json @@ -21,7 +21,7 @@ "_drift_manager": { "template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "template_dir": "nautobot-app", - "template_ref": "develop", + "template_ref": "refs/tags/nautobot-app-v2.1.0", "cookie_dir": "", "branch_prefix": "drift-manager", "pull_request_strategy": "create", @@ -29,7 +29,7 @@ "black" ], "draft": true, - "baked_commit_ref": "c6963e367d835faf66a9f4ac63267b6ce5811577" + "baked_commit_ref": "c9dce46b70f0154a56974587202e71e82ef08bae" } } } diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 8d0d0b23..8a9b4cf1 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -1,5 +1,5 @@ " +issue_format = "[#{issue}](https://github.com/nautobot/nautobot-app-golden-config/issues/{issue})" + +[[tool.towncrier.type]] +directory = "security" +name = "Security" +showcontent = true + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true + +[[tool.towncrier.type]] +directory = "dependencies" +name = "Dependencies" +showcontent = true + +[[tool.towncrier.type]] +directory = "documentation" +name = "Documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "housekeeping" +name = "Housekeeping" +showcontent = true diff --git a/tasks.py b/tasks.py index ae27bdca..d620399a 100644 --- a/tasks.py +++ b/tasks.py @@ -13,6 +13,8 @@ """ import os +from pathlib import Path +from time import sleep from invoke.collection import Collection from invoke.tasks import task as invoke_task @@ -67,6 +69,25 @@ def _is_compose_included(context, name): return f"docker-compose.{name}.yml" in context.nautobot_golden_config.compose_files +def _await_healthy_service(context, service): + container_id = docker_compose(context, f"ps -q -- {service}", pty=False, echo=False, hide=True).stdout.strip() + _await_healthy_container(context, container_id) + + +def _await_healthy_container(context, container_id): + while True: + result = context.run( + "docker inspect --format='{{.State.Health.Status}}' " + container_id, + pty=False, + echo=False, + hide=True, + ) + if result.stdout.strip() == "healthy": + break + print(f"Waiting for `{container_id}` container to become healthy ...") + sleep(1) + + def task(function=None, *args, **kwargs): """Task decorator to override the default Invoke task decorator and add each task to the invoke namespace.""" @@ -216,11 +237,46 @@ def stop(context, service=""): docker_compose(context, "stop" if service else "down --remove-orphans", service=service) -@task -def destroy(context): +@task( + aliases=("down",), + help={ + "volumes": "Remove Docker compose volumes (default: True)", + "import-db-file": "Import database from `import-db-file` file into the fresh environment (default: empty)", + }, +) +def destroy(context, volumes=True, import_db_file=""): """Destroy all containers and volumes.""" print("Destroying Nautobot...") - docker_compose(context, "down --remove-orphans --volumes") + docker_compose(context, f"down --remove-orphans {'--volumes' if volumes else ''}") + + if not import_db_file: + return + + if not volumes: + raise ValueError("Cannot specify `--no-volumes` and `--import-db-file` arguments at the same time.") + + print(f"Importing database file: {import_db_file}...") + + input_path = Path(import_db_file).absolute() + if not input_path.is_file(): + raise ValueError(f"File not found: {input_path}") + + command = [ + "run", + "--rm", + "--detach", + f"--volume='{input_path}:/docker-entrypoint-initdb.d/dump.sql'", + "--", + "db", + ] + + container_id = docker_compose(context, " ".join(command), pty=False, echo=False, hide=True).stdout.strip() + _await_healthy_container(context, container_id) + print("Stopping database container...") + context.run(f"docker stop {container_id}", pty=False, echo=False, hide=True) + + print("Database import complete, you can start Nautobot with the following command:") + print("invoke start") @task @@ -424,27 +480,43 @@ def dbshell(context, db_name="", input_file="", output_file="", query=""): @task( help={ + "db-name": "Database name to create (default: Nautobot database)", "input-file": "SQL dump file to replace the existing database with. This can be generated using `invoke backup-db` (default: `dump.sql`).", } ) -def import_db(context, input_file="dump.sql"): - """Stop Nautobot containers and replace the current database with the dump into the running `db` container.""" - docker_compose(context, "stop -- nautobot worker") +def import_db(context, db_name="", input_file="dump.sql"): + """Stop Nautobot containers and replace the current database with the dump into `db` container.""" + docker_compose(context, "stop -- nautobot worker beat") + start(context, "db") + _await_healthy_service(context, "db") command = ["exec -- db sh -c '"] if _is_compose_included(context, "mysql"): + if not db_name: + db_name = "$MYSQL_DATABASE" command += [ + "mysql --user root --password=$MYSQL_ROOT_PASSWORD", + '--execute="', + f"DROP DATABASE IF EXISTS {db_name};", + f"CREATE DATABASE {db_name};", + "" + if db_name == "$MYSQL_DATABASE" + else f"GRANT ALL PRIVILEGES ON {db_name}.* TO $MYSQL_USER; FLUSH PRIVILEGES;", + '"', + "&&", "mysql", - "--database=$MYSQL_DATABASE", + f"--database={db_name}", "--user=$MYSQL_USER", "--password=$MYSQL_PASSWORD", ] elif _is_compose_included(context, "postgres"): + if not db_name: + db_name = "$POSTGRES_DB" command += [ - "psql", - "--username=$POSTGRES_USER", - "postgres", + f"dropdb --if-exists --user=$POSTGRES_USER {db_name} &&", + f"createdb --user=$POSTGRES_USER {db_name} &&", + f"psql --user=$POSTGRES_USER --dbname={db_name}", ] else: raise ValueError("Unsupported database backend.") @@ -467,7 +539,10 @@ def import_db(context, input_file="dump.sql"): } ) def backup_db(context, db_name="", output_file="dump.sql", readable=True): - """Dump database into `output_file` file from running `db` container.""" + """Dump database into `output_file` file from `db` container.""" + start(context, "db") + _await_healthy_service(context, "db") + command = ["exec -- db sh -c '"] if _is_compose_included(context, "mysql"): @@ -475,17 +550,12 @@ def backup_db(context, db_name="", output_file="dump.sql", readable=True): "mysqldump", "--user=root", "--password=$MYSQL_ROOT_PASSWORD", - "--add-drop-database", "--skip-extended-insert" if readable else "", - "--databases", db_name if db_name else "$MYSQL_DATABASE", ] elif _is_compose_included(context, "postgres"): command += [ "pg_dump", - "--clean", - "--create", - "--if-exists", "--username=$POSTGRES_USER", f"--dbname={db_name or '$POSTGRES_DB'}", "--inserts" if readable else "", @@ -542,6 +612,19 @@ def help_task(context): context.run(f"invoke {task_name} --help") +@task( + help={ + "version": "Version of Golden Config to generate the release notes for.", + } +) +def generate_release_notes(context, version=""): + """Generate Release Notes using Towncrier.""" + command = "env DJANGO_SETTINGS_MODULE=nautobot.core.settings towncrier build" + if version: + command += f" --version {version}" + run_command(context, command) + + # ------------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------------ @@ -583,12 +666,34 @@ def pylint(context): run_command(context, command) -@task -def pydocstyle(context): - """Run pydocstyle to validate docstring formatting adheres to NTC defined standards.""" - # We exclude the /migrations/ directory since it is autogenerated code - command = "pydocstyle ." - run_command(context, command) +@task(aliases=("a",)) +def autoformat(context): + """Run code autoformatting.""" + black(context, autoformat=True) + ruff(context, fix=True) + + +@task( + help={ + "action": "One of 'lint', 'format', or 'both'", + "fix": "Automatically fix selected action. May not be able to fix all.", + "output_format": "see https://docs.astral.sh/ruff/settings/#output-format", + }, +) +def ruff(context, action="lint", fix=False, output_format="text"): + """Run ruff to perform code formatting and/or linting.""" + if action != "lint": + command = "ruff format" + if not fix: + command += " --check" + command += " ." + run_command(context, command) + if action != "format": + command = "ruff check" + if fix: + command += " --fix" + command += f" --output-format {output_format} ." + run_command(context, command) @task @@ -677,12 +782,12 @@ def tests(context, failfast=False, keepdb=False, lint_only=False): # Sorted loosely from fastest to slowest print("Running black...") black(context) + print("Running ruff...") + ruff(context) print("Running flake8...") flake8(context) print("Running bandit...") bandit(context) - print("Running pydocstyle...") - pydocstyle(context) print("Running yamllint...") yamllint(context) print("Running poetry check...") From 5fbee9fd465d60749cdb0b7f2cd7e59afad5d771 Mon Sep 17 00:00:00 2001 From: Jeff Kala <48843785+jeffkala@users.noreply.github.com> Date: Fri, 8 Mar 2024 13:50:08 -0700 Subject: [PATCH 10/17] Performance fixes, fix repos not syncing in "run all" jobs, move device-to-settings map to run once (#724) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * move qs inventory creation and device to settings map to before_task * perf: ⚡️ Change diff_files to use readlines instead of read for better performance during diff. * fix run all jobs not performing repo syncs * don't push repos we don't own * work through updated repo clone, sync, commit functionality * get tests passing * remove odd nfs file * move git repo stuff into decorator and stop using celery before and after primitives * finish up git repo sync, push, commit testcases * add changelog fragments * moved changelog fragments * fix unittest for non py311 versions * refactor to properly sync commit and push repos based on job and settings * add testcases for all jobs to validate repo syncs commits pushes --------- Co-authored-by: Justin Drew <2396364+jdrew82@users.noreply.github.com> --- changes/692.added | 1 + changes/692.changed | 1 + changes/692.fixed | 2 + nautobot_golden_config/jobs.py | 270 +++++--- .../nornir_plays/config_backup.py | 11 +- .../nornir_plays/config_compliance.py | 25 +- .../nornir_plays/config_intended.py | 24 +- nautobot_golden_config/tests/conftest.py | 57 +- nautobot_golden_config/tests/test_jobs.py | 619 ++++++++++++++++++ nautobot_golden_config/utilities/git.py | 10 +- 10 files changed, 875 insertions(+), 145 deletions(-) create mode 100755 changes/692.added create mode 100755 changes/692.changed create mode 100755 changes/692.fixed create mode 100755 nautobot_golden_config/tests/test_jobs.py diff --git a/changes/692.added b/changes/692.added new file mode 100755 index 00000000..a38f2294 --- /dev/null +++ b/changes/692.added @@ -0,0 +1 @@ +Add multiple new unittest test classes to validate repo syncing, commiting, and pushing logic. diff --git a/changes/692.changed b/changes/692.changed new file mode 100755 index 00000000..e5a1c980 --- /dev/null +++ b/changes/692.changed @@ -0,0 +1 @@ +Changed QuerySet and device_to_settings map into new decorator to run only one time instead of multiple. diff --git a/changes/692.fixed b/changes/692.fixed new file mode 100755 index 00000000..2d2f42e7 --- /dev/null +++ b/changes/692.fixed @@ -0,0 +1,2 @@ +Fixed performance issue on UNIX file diff view by reverting back to readlines(). +Fixed non-working repos list creation and syncing from run method to new decorator. diff --git a/nautobot_golden_config/jobs.py b/nautobot_golden_config/jobs.py index ec6c7f16..9131841b 100644 --- a/nautobot_golden_config/jobs.py +++ b/nautobot_golden_config/jobs.py @@ -1,10 +1,10 @@ """Jobs to run backups, intended config, and compliance.""" + # pylint: disable=too-many-function-args,logging-fstring-interpolation # TODO: Remove the following ignore, added to be able to pass pylint in CI. # pylint: disable=arguments-differ from datetime import datetime - from django.utils.timezone import make_aware from nautobot.core.celery import register_jobs from nautobot.dcim.models import Device, DeviceType, Location, Manufacturer, Platform, Rack, RackGroup @@ -19,8 +19,10 @@ StringVar, TextVar, ) -from nautobot.extras.models import DynamicGroup, GitRepository, Role, Status, Tag +from nautobot.extras.models import DynamicGroup, Role, Status, Tag from nautobot.tenancy.models import Tenant, TenantGroup +from nautobot_plugin_nornir.plugins.inventory.nautobot_orm import NautobotORMInventory +from nornir.core.plugins.inventory import InventoryPluginRegister from nornir_nautobot.exceptions import NornirNautobotException from nautobot_golden_config.choices import ConfigPlanTypeChoice from nautobot_golden_config.models import ComplianceFeature, ConfigPlan, GoldenConfig @@ -35,35 +37,106 @@ generate_config_set_from_manual, ) from nautobot_golden_config.utilities.git import GitRepo -from nautobot_golden_config.utilities.helper import get_job_filter +from nautobot_golden_config.utilities.helper import get_device_to_settings_map, get_job_filter + +InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory) name = "Golden Configuration" # pylint: disable=invalid-name -def get_refreshed_repos(job_obj, repo_type, data=None): +def get_repo_types_for_job(job_name): + """Logic to determine which repo_types are needed based on job + plugin settings.""" + repo_types = [] + if constant.ENABLE_BACKUP and job_name == "nautobot_golden_config.jobs.BackupJob": + repo_types.extend(["backup_repository"]) + if constant.ENABLE_INTENDED and job_name == "nautobot_golden_config.jobs.IntendedJob": + repo_types.extend(["jinja_repository", "intended_repository"]) + if constant.ENABLE_COMPLIANCE and job_name == "nautobot_golden_config.jobs.ComplianceJob": + repo_types.extend(["intended_repository", "backup_repository"]) + if "All" in job_name: + repo_types.extend(["backup_repository", "jinja_repository", "intended_repository"]) + return repo_types + + +def get_refreshed_repos(job_obj, repo_types, data=None): """Small wrapper to pull latest branch, and return a GitRepo app specific object.""" - devices = get_job_filter(data) dynamic_groups = DynamicGroup.objects.exclude(golden_config_setting__isnull=True) repository_records = set() - # Iterate through DynamicGroups then apply the DG's filter to the devices filtered by job. for group in dynamic_groups: - repo = getattr(group.golden_config_setting, repo_type, None) - if repo and devices.filter(group.generate_query()).exists(): - repository_records.add(repo.id) - - repositories = [] + # Make sure the data(device qs) device exist in the dg first. + if data.filter(group.generate_query()).exists(): + for repo_type in repo_types: + repo = getattr(group.golden_config_setting, repo_type, None) + if repo: + repository_records.add(repo) + + repositories = {} for repository_record in repository_records: - repo = GitRepository.objects.get(id=repository_record) - ensure_git_repository(repo, job_obj.logger) + ensure_git_repository(repository_record, job_obj.logger) # TODO: Should this not point to non-nautobot.core import # We should ask in nautobot core for the `from_url` constructor to be it's own function - git_info = get_repo_from_url_to_path_and_from_branch(repo) - git_repo = GitRepo(repo.filesystem_path, git_info.from_url, clone_initially=False, base_url=repo.remote_url) - repositories.append(git_repo) - + git_info = get_repo_from_url_to_path_and_from_branch(repository_record) + git_repo = GitRepo( + repository_record.filesystem_path, + git_info.from_url, + clone_initially=False, + base_url=repository_record.remote_url, + nautobot_repo_obj=repository_record, + ) + commit = False + + if ( + constant.ENABLE_INTENDED + and "nautobot_golden_config.intendedconfigs" in git_repo.nautobot_repo_obj.provided_contents + ): + commit = True + if ( + constant.ENABLE_BACKUP + and "nautobot_golden_config.backupconfigs" in git_repo.nautobot_repo_obj.provided_contents + ): + commit = True + repositories[str(git_repo.nautobot_repo_obj.id)] = {"repo_obj": git_repo, "to_commit": commit} return repositories +def gc_repos(func): + """Decorator used for handle repo syncing, commiting, and pushing.""" + + def gc_repo_wrapper(self, *args, **kwargs): + """Decorator used for handle repo syncing, commiting, and pushing.""" + self.logger.debug("Compiling device data for GC job.", extra={"grouping": "Get Job Filter"}) + self.qs = get_job_filter(kwargs) + self.logger.debug( + f"In scope device count for this job: {self.qs.count()}", extra={"grouping": "Get Job Filter"} + ) + self.logger.debug("Mapping device(s) to GC Settings.", extra={"grouping": "Device to Settings Map"}) + self.device_to_settings_map = get_device_to_settings_map(queryset=self.qs) + gitrepo_types = list(set(get_repo_types_for_job(self.name))) + self.logger.debug( + f"Repository types to sync: {', '.join(sorted(gitrepo_types))}", + extra={"grouping": "GC Repo Syncs"}, + ) + current_repos = get_refreshed_repos(job_obj=self, repo_types=gitrepo_types, data=self.qs) + # This is where the specific jobs run method runs via this decorator. + func(self, *args, **kwargs) + now = make_aware(datetime.now()) + self.logger.debug( + f"Finished the {self.Meta.name} job execution.", + extra={"grouping": "GC After Run"}, + ) + if current_repos: + for _, repo in current_repos.items(): + if repo["to_commit"]: + self.logger.debug( + f"Pushing {self.Meta.name} results to repo {repo['repo_obj'].base_url}.", + extra={"grouping": "GC Repo Commit and Push"}, + ) + repo["repo_obj"].commit_with_added(f"{self.Meta.name.upper()} JOB {now}") + repo["repo_obj"].push() + + return gc_repo_wrapper + + class FormEntry: # pylint disable=too-few-public-method """Class definition to use as Mixin for form definitions.""" @@ -91,39 +164,13 @@ class FormEntry: # pylint disable=too-few-public-method class GoldenConfigJobMixin(Job): # pylint: disable=abstract-method - """Reused mixin to be able to reuse common celery primitives in all GC jobs.""" + """Reused mixin to be able to set defaults for instance attributes in all GC jobs.""" - def before_start(self, task_id, args, kwargs): - """Ensure repos before tasks runs.""" - super().before_start(task_id, args, kwargs) - self.repos = [] - self.logger.debug( - f"Repository types to sync: {', '.join(self.Meta.repo_types)}", # pylint: disable=no-member - extra={"grouping": "GC Repo Syncs"}, - ) - for repo_type in self.Meta.repo_types: # pylint: disable=no-member - self.logger.debug(f"Refreshing repositories of type {repo_type}.", extra={"grouping": "GC Repo Syncs"}) - current_repos = get_refreshed_repos(job_obj=self, repo_type=repo_type, data=self.deserialize_data(kwargs)) - if not repo_type == "jinja_repository": - for current_repo in current_repos: - self.repos.append(current_repo) - - def after_return(self, status, retval, task_id, args, kwargs, einfo): # pylint: disable=too-many-arguments - """Commit and Push each repo after job is completed.""" - now = make_aware(datetime.now()) - self.logger.debug( - f"Finished the {self.Meta.name} job execution.", # pylint: disable=no-member - extra={"grouping": "GC After Run"}, - ) - if self.repos: - for repo in self.repos: - self.logger.debug( - f"Pushing {self.Meta.name} results to repo {repo.base_url}.", # pylint: disable=no-member - extra={"grouping": "GC Repo Commit and Push"}, - ) - repo.commit_with_added(f"{self.Meta.name.upper()} JOB {now}") # pylint: disable=no-member - repo.push() - super().after_return(status, retval, task_id, args, kwargs, einfo=einfo) + def __init__(self, *args, **kwargs): + """Initialize the job.""" + super().__init__(*args, **kwargs) + self.qs = None + self.device_to_settings_map = {} class ComplianceJob(GoldenConfigJobMixin, FormEntry): @@ -135,16 +182,20 @@ class Meta: name = "Perform Configuration Compliance" description = "Run configuration compliance on your network infrastructure." has_sensitive_variables = False - repo_types = ["intended_repository", "backup_repository"] - def run(self, *args, **data): + @gc_repos + def run(self, *args, **data): # pylint: disable=unused-argument """Run config compliance report script.""" - self.logger.debug("Starting config compliance nornir play.") - config_compliance(self.job_result, self.logger.getEffectiveLevel(), data) - - def after_return(self, *args): - """Commit and Push each repo after job is completed.""" - self.logger.debug("Compliance job completed, no repositories need to be synced in this task.") + self.logger.warning("Starting config compliance nornir play.") + if not constant.ENABLE_COMPLIANCE: + self.logger.critical("Compliance is disabled in application settings.") + raise ValueError("Compliance is disabled in application settings.") + config_compliance( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, # pylint: disable=no-member + self.device_to_settings_map, # pylint: disable=no-member + ) class IntendedJob(GoldenConfigJobMixin, FormEntry): @@ -156,12 +207,21 @@ class Meta: name = "Generate Intended Configurations" description = "Generate the configuration for your intended state." has_sensitive_variables = False - repo_types = ["jinja_repository", "intended_repository"] - def run(self, *args, **data): + @gc_repos + def run(self, *args, **data): # pylint: disable=unused-argument """Run config generation script.""" self.logger.debug("Building device settings mapping and running intended config nornir play.") - config_intended(self.job_result, self.logger.getEffectiveLevel(), data, self) + if not constant.ENABLE_INTENDED: + self.logger.critical("Intended Generation is disabled in application settings.") + raise ValueError("Intended Generation is disabled in application settings.") + config_intended( + self.job_result, + self.logger.getEffectiveLevel(), + self, + self.qs, # pylint: disable=no-member + self.device_to_settings_map, # pylint: disable=no-member + ) class BackupJob(GoldenConfigJobMixin, FormEntry): @@ -173,12 +233,20 @@ class Meta: name = "Backup Configurations" description = "Backup the configurations of your network devices." has_sensitive_variables = False - repo_types = ["backup_repository"] - def run(self, *args, **data): + @gc_repos + def run(self, *args, **data): # pylint: disable=unused-argument """Run config backup process.""" self.logger.debug("Starting config backup nornir play.") - config_backup(self.job_result, self.logger.getEffectiveLevel(), data) + if not constant.ENABLE_BACKUP: + self.logger.critical("Backups are disabled in application settings.") + raise ValueError("Backups are disabled in application settings.") + config_backup( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, + self.device_to_settings_map, + ) class AllGoldenConfig(GoldenConfigJobMixin): @@ -193,26 +261,32 @@ class Meta: name = "Execute All Golden Configuration Jobs - Single Device" description = "Process to run all Golden Configuration jobs configured." has_sensitive_variables = False - repo_types = [] - def run(self, *args, **data): - """Run all jobs.""" - repo_types = [] + @gc_repos + def run(self, *args, **data): # pylint: disable=unused-argument + """Run all jobs on a single device.""" if constant.ENABLE_INTENDED: - repo_types.extend(["jinja_repository", "intended_repository"]) - if constant.ENABLE_BACKUP: - repo_types.extend(["backup_repository"]) - repo_types = list(set(repo_types) - set()) - if constant.ENABLE_COMPLIANCE: - repo_types.extend(["intended_repository", "backup_repository"]) - - self.Meta.repo_types = repo_types - if constant.ENABLE_INTENDED: - IntendedJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_intended( + self.job_result, + self.logger.getEffectiveLevel(), + self, + self.qs, + self.device_to_settings_map, + ) if constant.ENABLE_BACKUP: - BackupJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_backup( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, + self.device_to_settings_map, + ) if constant.ENABLE_COMPLIANCE: - ComplianceJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_compliance( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, + self.device_to_settings_map, + ) class AllDevicesGoldenConfig(GoldenConfigJobMixin, FormEntry): @@ -224,26 +298,32 @@ class Meta: name = "Execute All Golden Configuration Jobs - Multiple Device" description = "Process to run all Golden Configuration jobs configured against multiple devices." has_sensitive_variables = False - repo_types = [] - - def run(self, *args, **data): - """Run all jobs.""" - repo_types = [] - if constant.ENABLE_INTENDED: - repo_types.extend(["jinja_repository", "intended_repository"]) - if constant.ENABLE_BACKUP: - repo_types.extend(["backup_repository"]) - repo_types = list(set(repo_types) - set()) - if constant.ENABLE_COMPLIANCE: - repo_types.extend(["intended_repository", "backup_repository"]) - self.Meta.repo_types = repo_types + @gc_repos + def run(self, *args, **data): # pylint: disable=unused-argument + """Run all jobs on multiple devices.""" if constant.ENABLE_INTENDED: - IntendedJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_intended( + self.job_result, + self.logger.getEffectiveLevel(), + self, + self.qs, + self.device_to_settings_map, + ) if constant.ENABLE_BACKUP: - BackupJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_backup( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, + self.device_to_settings_map, + ) if constant.ENABLE_COMPLIANCE: - ComplianceJob().run.__func__(self, **data) # pylint: disable=too-many-function-args + config_compliance( + self.job_result, + self.logger.getEffectiveLevel(), + self.qs, + self.device_to_settings_map, + ) class GenerateConfigPlans(Job, FormEntry): diff --git a/nautobot_golden_config/nornir_plays/config_backup.py b/nautobot_golden_config/nornir_plays/config_backup.py index 1eedb6cb..69d12b01 100644 --- a/nautobot_golden_config/nornir_plays/config_backup.py +++ b/nautobot_golden_config/nornir_plays/config_backup.py @@ -12,14 +12,11 @@ from nornir.core.task import Result, Task from nornir_nautobot.exceptions import NornirNautobotException from nornir_nautobot.plugins.tasks.dispatcher import dispatcher - from nautobot_golden_config.models import ConfigRemove, ConfigReplace, GoldenConfig from nautobot_golden_config.nornir_plays.processor import ProcessGoldenConfig from nautobot_golden_config.utilities.db_management import close_threaded_db_connections -from nautobot_golden_config.utilities.helper import ( +from nautobot_golden_config.utilities.helper import ( # get_device_to_settings_map,; get_job_filter, dispatch_params, - get_device_to_settings_map, - get_job_filter, render_jinja_template, verify_settings, ) @@ -85,15 +82,11 @@ def run_backup( # pylint: disable=too-many-arguments return Result(host=task.host, result=running_config) -def config_backup(job_result, log_level, data): +def config_backup(job_result, log_level, qs, device_to_settings_map): """Nornir play to backup configurations.""" now = make_aware(datetime.now()) logger = NornirLogger(job_result, log_level) - qs = get_job_filter(data) - logger.debug("Compiling device data for backup.") - device_to_settings_map = get_device_to_settings_map(queryset=qs) - for settings in set(device_to_settings_map.values()): verify_settings(logger, settings, ["backup_path_template"]) diff --git a/nautobot_golden_config/nornir_plays/config_compliance.py b/nautobot_golden_config/nornir_plays/config_compliance.py index f6e6edaf..bb3ad3c5 100644 --- a/nautobot_golden_config/nornir_plays/config_compliance.py +++ b/nautobot_golden_config/nornir_plays/config_compliance.py @@ -1,12 +1,13 @@ """Nornir job for generating the compliance data.""" + # pylint: disable=relative-beyond-top-level import difflib import logging import os from collections import defaultdict from datetime import datetime -from django.utils.timezone import make_aware +from django.utils.timezone import make_aware from nautobot_plugin_nornir.constants import NORNIR_SETTINGS from nautobot_plugin_nornir.plugins.inventory.nautobot_orm import NautobotORMInventory from netutils.config.compliance import _open_file_config, parser_map, section_config @@ -14,19 +15,12 @@ from nornir.core.plugins.inventory import InventoryPluginRegister from nornir.core.task import Result, Task from nornir_nautobot.exceptions import NornirNautobotException - from nautobot_golden_config.choices import ComplianceRuleConfigTypeChoice -from nautobot_golden_config.utilities.logger import NornirLogger from nautobot_golden_config.models import ComplianceRule, ConfigCompliance, GoldenConfig from nautobot_golden_config.nornir_plays.processor import ProcessGoldenConfig from nautobot_golden_config.utilities.db_management import close_threaded_db_connections -from nautobot_golden_config.utilities.helper import ( - get_device_to_settings_map, - get_job_filter, - get_json_config, - render_jinja_template, - verify_settings, -) +from nautobot_golden_config.utilities.helper import get_json_config, render_jinja_template, verify_settings +from nautobot_golden_config.utilities.logger import NornirLogger InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory) LOGGER = logging.getLogger(__name__) @@ -88,9 +82,9 @@ def get_config_element(rule, config, obj, logger): def diff_files(backup_file, intended_file): """Utility function to provide `Unix Diff` between two files.""" with open(backup_file, encoding="utf-8") as file: - backup = file.read() + backup = file.readlines() with open(intended_file, encoding="utf-8") as file: - intended = file.read() + intended = file.readlines() for line in difflib.unified_diff(backup, intended, lineterm=""): yield line @@ -174,18 +168,13 @@ def run_compliance( # pylint: disable=too-many-arguments,too-many-locals return Result(host=task.host) -def config_compliance(job_result, log_level, data): +def config_compliance(job_result, log_level, qs, device_to_settings_map): """Nornir play to generate configurations.""" now = make_aware(datetime.now()) logger = NornirLogger(job_result, log_level) rules = get_rules() - qs = get_job_filter(data) - logger.debug("Compiling device data for compliance job.") - - device_to_settings_map = get_device_to_settings_map(queryset=qs) - for settings in set(device_to_settings_map.values()): verify_settings(logger, settings, ["backup_path_template", "intended_path_template"]) diff --git a/nautobot_golden_config/nornir_plays/config_intended.py b/nautobot_golden_config/nornir_plays/config_intended.py index d326b206..0b24b7b5 100644 --- a/nautobot_golden_config/nornir_plays/config_intended.py +++ b/nautobot_golden_config/nornir_plays/config_intended.py @@ -5,32 +5,26 @@ from datetime import datetime from django.utils.timezone import make_aware - -from nautobot_plugin_nornir.constants import NORNIR_SETTINGS -from nautobot_plugin_nornir.plugins.inventory.nautobot_orm import NautobotORMInventory - from nornir import InitNornir from nornir.core.plugins.inventory import InventoryPluginRegister from nornir.core.task import Result, Task from nornir_nautobot.exceptions import NornirNautobotException from nornir_nautobot.plugins.tasks.dispatcher import dispatcher - +from nautobot_plugin_nornir.constants import NORNIR_SETTINGS +from nautobot_plugin_nornir.plugins.inventory.nautobot_orm import NautobotORMInventory from nautobot_golden_config.models import GoldenConfig - from nautobot_golden_config.nornir_plays.processor import ProcessGoldenConfig from nautobot_golden_config.utilities.db_management import close_threaded_db_connections - from nautobot_golden_config.utilities.graphql import graph_ql_query from nautobot_golden_config.utilities.helper import ( dispatch_params, get_django_env, - get_device_to_settings_map, - get_job_filter, render_jinja_template, verify_settings, ) from nautobot_golden_config.utilities.logger import NornirLogger + InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory) LOGGER = logging.getLogger(__name__) @@ -96,7 +90,7 @@ def run_template( # pylint: disable=too-many-arguments,too-many-locals return Result(host=task.host, result=generated_config) -def config_intended(job_result, log_level, data, job_class_instance): +def config_intended(job_result, log_level, job_class_instance, qs, device_to_settings_map): """ Nornir play to generate configurations. @@ -111,16 +105,6 @@ def config_intended(job_result, log_level, data, job_class_instance): now = make_aware(datetime.now()) logger = NornirLogger(job_result, log_level) - try: - qs = get_job_filter(data) - except NornirNautobotException as error: - error_msg = f"`E3008:` General Exception handler, original error message ```{error}```" - logger.error(error_msg) - raise NornirNautobotException(error_msg) from error - - logger.debug("Compiling device data for intended configuration.") - device_to_settings_map = get_device_to_settings_map(queryset=qs) - for settings in set(device_to_settings_map.values()): verify_settings(logger, settings, ["jinja_path_template", "intended_path_template", "sot_agg_query"]) diff --git a/nautobot_golden_config/tests/conftest.py b/nautobot_golden_config/tests/conftest.py index c9c621bf..254ff3be 100644 --- a/nautobot_golden_config/tests/conftest.py +++ b/nautobot_golden_config/tests/conftest.py @@ -7,9 +7,10 @@ from nautobot.dcim.models import Device, DeviceType, Location, LocationType, Manufacturer, Platform, Rack, RackGroup from nautobot.extras.choices import JobResultStatusChoices from nautobot.extras.datasources.registry import get_datasource_contents -from nautobot.extras.models import GitRepository, GraphQLQuery, JobResult, Role, Status, Tag +from nautobot.extras.models import GitRepository, GraphQLQuery, JobResult, Role, Status, Tag, DynamicGroup from nautobot.tenancy.models import Tenant, TenantGroup import pytz +from nautobot_golden_config.models import GoldenConfigSetting from nautobot_golden_config.choices import ComplianceRuleConfigTypeChoice from nautobot_golden_config.models import ComplianceFeature, ComplianceRule, ConfigCompliance @@ -230,7 +231,9 @@ def create_orphan_device(name="orphan"): manufacturer, _ = Manufacturer.objects.get_or_create(name="Manufacturer 4") device_role, _ = Role.objects.get_or_create(name="Role 4") device_type, _ = DeviceType.objects.get_or_create(manufacturer=manufacturer, model="Device Type 4") - platform, _ = Platform.objects.get_or_create(manufacturer=manufacturer, name="Platform 4") + platform, _ = Platform.objects.get_or_create( + manufacturer=manufacturer, name="Platform 4", network_driver="cisco_ios" + ) tag, _ = Tag.objects.get_or_create(name="Orphaned") tag.content_types.add(ct_device) device = Device.objects.create( @@ -518,3 +521,53 @@ def create_job_result() -> None: result.completed = datetime.now(pytz.UTC) result.validated_save() return result + + +def dgs_gc_settings_and_job_repo_objects(): + """Create Multiple DGS GC settings and other objects.""" + create_git_repos() + create_saved_queries() + # Since we enforce a singleton pattern on this model, nuke the auto-created object. + GoldenConfigSetting.objects.all().delete() + + dynamic_group1 = DynamicGroup.objects.create( + name="dg foobaz", + content_type=ContentType.objects.get_for_model(Device), + filter={"platform": ["Platform 1"]}, + ) + dynamic_group2 = DynamicGroup.objects.create( + name="dg foobaz2", + content_type=ContentType.objects.get_for_model(Device), + filter={"platform": ["Platform 4"]}, + ) + + GoldenConfigSetting.objects.create( + name="test_name", + slug="test_slug", + weight=1000, + description="Test Description.", + backup_path_template="test/backup", + intended_path_template="test/intended", + jinja_path_template="{{jinja_path}}", + backup_test_connectivity=True, + dynamic_group=dynamic_group1, + sot_agg_query=GraphQLQuery.objects.get(name="GC-SoTAgg-Query-1"), + backup_repository=GitRepository.objects.get(name="test-backup-repo-1"), + intended_repository=GitRepository.objects.get(name="test-intended-repo-1"), + jinja_repository=GitRepository.objects.get(name="test-jinja-repo-1"), + ) + GoldenConfigSetting.objects.create( + name="test_name2", + slug="test_slug2", + weight=1000, + description="Test Description.", + backup_path_template="test/backup", + intended_path_template="test/intended", + jinja_path_template="{{jinja_path}}", + backup_test_connectivity=True, + dynamic_group=dynamic_group2, + sot_agg_query=GraphQLQuery.objects.get(name="GC-SoTAgg-Query-1"), + backup_repository=GitRepository.objects.get(name="test-backup-repo-2"), + intended_repository=GitRepository.objects.get(name="test-intended-repo-2"), + jinja_repository=GitRepository.objects.get(name="test-jinja-repo-1"), + ) diff --git a/nautobot_golden_config/tests/test_jobs.py b/nautobot_golden_config/tests/test_jobs.py new file mode 100755 index 00000000..fcf099a5 --- /dev/null +++ b/nautobot_golden_config/tests/test_jobs.py @@ -0,0 +1,619 @@ +"""Basic Job Test.""" +from unittest.mock import patch, MagicMock +from nautobot.apps.testing import TransactionTestCase, create_job_result_and_run_job +from nautobot.extras.models import JobLogEntry +from nautobot.dcim.models import Device +from nautobot_golden_config.tests.conftest import ( + create_device, + create_orphan_device, + dgs_gc_settings_and_job_repo_objects, +) +from nautobot_golden_config.utilities import constant +from nautobot_golden_config import jobs + + +@patch("nautobot_golden_config.nornir_plays.config_backup.run_backup", MagicMock(return_value="foo")) +@patch.object(jobs, "ensure_git_repository") +class GCReposBackupTestCase(TransactionTestCase): + """Test the repos to sync and commit are working for backup job.""" + + databases = ("default", "job_logs") + + def setUp(self) -> None: + """Setup test data.""" + self.device = create_device(name="foobaz") + self.device2 = create_orphan_device(name="foobaz2") + dgs_gc_settings_and_job_repo_objects() + super().setUp() + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", True) + def test_backup_job_repos_one_setting(self, mock_ensure_git_repository): + """Test backup job repo-types are backup only.""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="BackupJob", device=Device.objects.filter(name=self.device.name) + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: backup_repository") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Backup Configurations job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", True) + def test_backup_job_repos_two_setting(self, mock_ensure_git_repository): + """Test backup job repo-types are backup only.""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", + name="BackupJob", + device=Device.objects.all(), + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: backup_repository") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Backup Configurations job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + def test_backup_job_repos_one_setting_backup_disabled(self, mock_ensure_git_repository): + """Test backup job repo-types are backup only.""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_BACKUP) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="BackupJob", device=Device.objects.filter(name=self.device.name) + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Backups are disabled in application settings.") + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + def test_backup_job_repos_two_setting_backup_disabled(self, mock_ensure_git_repository): + """Test backup job repo-types are backup only.""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_BACKUP) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="BackupJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Backups are disabled in application settings.") + + +@patch("nautobot_golden_config.nornir_plays.config_intended.run_template", MagicMock(return_value="foo")) +@patch.object(jobs, "ensure_git_repository") +class GCReposIntendedTestCase(TransactionTestCase): + """Test the repos to sync and commit are working for intended job.""" + + databases = ("default", "job_logs") + + def setUp(self) -> None: + """Setup test data.""" + self.device = create_device(name="foobaz") + self.device2 = create_orphan_device(name="foobaz2") + dgs_gc_settings_and_job_repo_objects() + super().setUp() + + def test_intended_job_repos_one_setting(self, mock_ensure_git_repository): + """Test intended job one GC setting enabled_intended enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", + name="IntendedJob", + device=Device.objects.filter(name=self.device.name), + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: intended_repository, jinja_repository") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Generate Intended Configurations job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + def test_intended_job_repos_two_setting(self, mock_ensure_git_repository): + """Test intended job two GC setting enabled_intended enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="IntendedJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: intended_repository, jinja_repository") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Generate Intended Configurations job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_intended_job_repos_one_setting_intended_disabled(self, mock_ensure_git_repository): + """Test intended job one GC setting enabled_intended disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_INTENDED) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", + name="IntendedJob", + device=Device.objects.filter(name=self.device.name), + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Intended Generation is disabled in application settings.") + + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_intended_job_repos_two_setting_intended_disabled(self, mock_ensure_git_repository): + """Test intended job two GC setting enabled_intended disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_INTENDED) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="IntendedJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Intended Generation is disabled in application settings.") + + +@patch("nautobot_golden_config.nornir_plays.config_compliance.run_compliance", MagicMock(return_value="foo")) +@patch.object(jobs, "ensure_git_repository") +class GCReposComplianceTestCase(TransactionTestCase): + """Test the repos to sync and commit are working for compliance job.""" + + databases = ("default", "job_logs") + + def setUp(self) -> None: + """Setup test data.""" + self.device = create_device(name="foobaz") + self.device2 = create_orphan_device(name="foobaz2") + dgs_gc_settings_and_job_repo_objects() + super().setUp() + + def test_compliance_job_repos_one_setting(self, mock_ensure_git_repository): + """Test compliance job one GC setting enabled_compliance enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", + name="ComplianceJob", + device=Device.objects.filter(name=self.device.name), + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, "Repository types to sync: backup_repository, intended_repository" + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Perform Configuration Compliance job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + def test_compliance_job_repos_two_setting(self, mock_ensure_git_repository): + """Test compliance job two GC setting enabled_compliance enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="ComplianceJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, "Repository types to sync: backup_repository, intended_repository" + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Perform Configuration Compliance job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_COMPLIANCE", False) + def test_compliance_job_repos_one_setting_compliance_disabled(self, mock_ensure_git_repository): + """Test compliance job one GC setting enabled_compliance disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_COMPLIANCE) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", + name="ComplianceJob", + device=Device.objects.filter(name=self.device.name), + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Compliance is disabled in application settings.") + + @patch("nautobot_golden_config.utilities.constant.ENABLE_COMPLIANCE", False) + def test_compliance_job_repos_two_setting_compliance_disabled(self, mock_ensure_git_repository): + """Test compliance job two GC setting enabled_compliance disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_COMPLIANCE) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="ComplianceJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual(log_entries.first().message, "Repository types to sync: ") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="run") + self.assertEqual(log_entries.last().message, "Compliance is disabled in application settings.") + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + def test_compliance_job_repos_backup_disabled(self, mock_ensure_git_repository): + """Test compliance job one GC setting enabled_backup disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_BACKUP) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="ComplianceJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, "Repository types to sync: backup_repository, intended_repository" + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Perform Configuration Compliance job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_compliance_job_repos_intended_disabled(self, mock_ensure_git_repository): + """Test compliance job one GC setting enabled_intended disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_INTENDED) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="ComplianceJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, "Repository types to sync: backup_repository, intended_repository" + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Perform Configuration Compliance job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_compliance_job_repos_both_disabled(self, mock_ensure_git_repository): + """Test compliance job one GC setting both disabled""" + mock_ensure_git_repository.return_value = True + self.assertFalse(constant.ENABLE_BACKUP) + self.assertFalse(constant.ENABLE_INTENDED) + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="ComplianceJob", device=Device.objects.all() + ) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, "Repository types to sync: backup_repository, intended_repository" + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual(log_entries.first().message, "Finished the Perform Configuration Compliance job execution.") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 0) + + +@patch("nautobot_golden_config.nornir_plays.config_backup.run_backup", MagicMock(return_value="foo")) +@patch("nautobot_golden_config.nornir_plays.config_intended.run_template", MagicMock(return_value="foo")) +@patch("nautobot_golden_config.nornir_plays.config_compliance.run_compliance", MagicMock(return_value="foo")) +@patch.object(jobs, "ensure_git_repository") +class GCReposRunAllSingleTestCase(TransactionTestCase): + """Test the repos to sync and commit are working for run all single job.""" + + databases = ("default", "job_logs") + + def setUp(self) -> None: + """Setup test data.""" + self.device = create_device(name="foobaz") + dgs_gc_settings_and_job_repo_objects() + super().setUp() + + def test_run_all_job_single_repos(self, mock_ensure_git_repository): + """Test run all job single on one GC setting enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllGoldenConfig", device=self.device.id + ) + self.assertTrue(constant.ENABLE_BACKUP) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Single Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + def test_run_all_job_single_repos_backup_disabled(self, mock_ensure_git_repository): + """Test run all job single on one GC backup_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllGoldenConfig", device=self.device.id + ) + self.assertFalse(constant.ENABLE_BACKUP) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Single Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_run_all_job_single_repos_intended_disabled(self, mock_ensure_git_repository): + """Test run all job single on one GC intended_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllGoldenConfig", device=self.device.id + ) + self.assertFalse(constant.ENABLE_INTENDED) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Single Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_run_all_job_single_repos_both_disabled(self, mock_ensure_git_repository): + """Test run all job single on one GC both_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllGoldenConfig", device=self.device.id + ) + self.assertFalse(constant.ENABLE_BACKUP) + self.assertFalse(constant.ENABLE_INTENDED) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 1") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Single Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 0) + + +@patch("nautobot_golden_config.nornir_plays.config_backup.run_backup", MagicMock(return_value="foo")) +@patch("nautobot_golden_config.nornir_plays.config_intended.run_template", MagicMock(return_value="foo")) +@patch("nautobot_golden_config.nornir_plays.config_compliance.run_compliance", MagicMock(return_value="foo")) +@patch.object(jobs, "ensure_git_repository") +class GCReposRunAllMultipleTestCase(TransactionTestCase): + """Test the repos to sync and commit are working for run all multiple job.""" + + databases = ("default", "job_logs") + + def setUp(self) -> None: + """Setup test data.""" + self.device = create_device(name="foobaz") + self.device2 = create_orphan_device(name="foobaz2") + dgs_gc_settings_and_job_repo_objects() + super().setUp() + + def test_run_all_job_multiple_repos(self, mock_ensure_git_repository): + """Test run all job multiple on one GC setting enabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllDevicesGoldenConfig", device=Device.objects.all() + ) + self.assertTrue(constant.ENABLE_BACKUP) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Multiple Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + def test_run_all_job_multiple_repos_backup_disabled(self, mock_ensure_git_repository): + """Test run all job multiple on one GC backup_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllDevicesGoldenConfig", device=Device.objects.all() + ) + self.assertFalse(constant.ENABLE_BACKUP) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Multiple Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_run_all_job_multiple_repos_intended_disabled(self, mock_ensure_git_repository): + """Test run all job multiple on one GC intended_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllDevicesGoldenConfig", device=Device.objects.all() + ) + self.assertFalse(constant.ENABLE_INTENDED) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Multiple Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 1) + + @patch("nautobot_golden_config.utilities.constant.ENABLE_BACKUP", False) + @patch("nautobot_golden_config.utilities.constant.ENABLE_INTENDED", False) + def test_run_all_job_multiple_repos_both_disabled(self, mock_ensure_git_repository): + """Test run all job multiple on one GC both_disabled""" + mock_ensure_git_repository.return_value = True + job_result = create_job_result_and_run_job( + module="nautobot_golden_config.jobs", name="AllDevicesGoldenConfig", device=Device.objects.all() + ) + self.assertFalse(constant.ENABLE_BACKUP) + self.assertFalse(constant.ENABLE_INTENDED) + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Syncs") + self.assertEqual( + log_entries.first().message, + "Repository types to sync: backup_repository, intended_repository, jinja_repository", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="Get Job Filter") + self.assertEqual(log_entries.count(), 2) + self.assertEqual(log_entries.last().message, "In scope device count for this job: 2") + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC After Run") + self.assertEqual( + log_entries.first().message, + "Finished the Execute All Golden Configuration Jobs - Multiple Device job execution.", + ) + + log_entries = JobLogEntry.objects.filter(job_result=job_result, grouping="GC Repo Commit and Push") + self.assertEqual(log_entries.count(), 0) diff --git a/nautobot_golden_config/utilities/git.py b/nautobot_golden_config/utilities/git.py index ad5902a4..f1cabacc 100644 --- a/nautobot_golden_config/utilities/git.py +++ b/nautobot_golden_config/utilities/git.py @@ -9,10 +9,18 @@ class GitRepo(_GitRepo): # pylint: disable=too-many-instance-attributes """Git Repo object to help with git actions.""" - def __init__(self, path, url, clone_initially=True, base_url=None): + def __init__( # pylint: disable=too-many-arguments + self, + path, + url, + clone_initially=True, + base_url=None, + nautobot_repo_obj=None, + ): """Set attributes to easily interact with Git Repositories.""" super().__init__(path, url, clone_initially) self.base_url = base_url + self.nautobot_repo_obj = nautobot_repo_obj def commit_with_added(self, commit_description): """Make a force commit. From d018661a2f8c8c8265e4676e214e0982e6496968 Mon Sep 17 00:00:00 2001 From: Nautobot-Bot <79372327+nautobot-bot@users.noreply.github.com> Date: Sat, 9 Mar 2024 06:55:42 -0600 Subject: [PATCH 11/17] Cookie updated by NetworkToCode Cookie Drift Manager Tool (#730) * Cookie updated by NetworkToCode Cookie Drift Manager Tool Template: ``` { "template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "dir": "nautobot-app", "ref": "refs/tags/nautobot-app-v2.2.0", "path": null } ``` Cookie: ``` { "remote": "https://github.com/nautobot/nautobot-app-golden-config.git", "path": "/tmp/tmptjpgbanq/nautobot-app-golden-config", "repository_path": "/tmp/tmptjpgbanq/nautobot-app-golden-config", "dir": "", "branch_prefix": "drift-manager", "context": { "codeowner_github_usernames": "@itdependsnetworks @jeffkala @nkallergis", "full_name": "Network to Code, LLC", "email": "opensource@networktocode.com", "github_org": "nautobot", "app_name": "nautobot_golden_config", "verbose_name": "Golden Config", "app_slug": "nautobot-golden-config", "project_slug": "nautobot-app-golden-config", "repo_url": "https://github.com/nautobot/nautobot-app-golden-config", "base_url": "golden-config", "min_nautobot_version": "2.0.0", "max_nautobot_version": "2.9999", "camel_name": "NautobotGoldenConfig", "project_short_description": "An app for configuration on nautobot", "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/golden-config/en/latest", "_template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "_output_dir": "/tmp/tmptjpgbanq", "_repo_dir": "/github/home/.cookiecutters/cookiecutter-nautobot-app/nautobot-app", "_checkout": "refs/tags/nautobot-app-v2.2.0" }, "base_branch": "develop", "remote_name": "origin", "pull_request_strategy": "PullRequestStrategy.CREATE", "post_actions": [ "PostAction.BLACK" ], "baked_commit_ref": "c9dce46b70f0154a56974587202e71e82ef08bae", "draft": true } ``` CLI Arguments: ``` { "cookie_dir": "", "input": false, "json_filename": "", "output_dir": "", "push": true, "template": "", "template_dir": "", "template_ref": "refs/tags/nautobot-app-v2.2.0", "pull_request": null, "post_action": [], "disable_post_actions": false, "draft": null } ``` --------- Co-authored-by: bakebot Co-authored-by: Jan Snasel --- .cookiecutter.json | 4 +- .../pull_request_template.md | 1 - .github/workflows/ci.yml | 72 +++++-------------- changes/8.housekeeping | 1 + development/Dockerfile | 2 +- development/app_config_schema.py | 64 +++++++++++++++++ development/nautobot_config.py | 4 +- development/towncrier_template.j2 | 2 +- docs/admin/install.md | 2 +- docs/dev/contributing.md | 42 +++++------ docs/dev/dev_environment.md | 20 +++++- mkdocs.yml | 6 +- nautobot_golden_config/app-config-schema.json | 1 + poetry.lock | 18 ++++- pyproject.toml | 4 +- tasks.py | 54 ++++++++++++-- 16 files changed, 199 insertions(+), 98 deletions(-) create mode 100644 changes/8.housekeeping create mode 100644 development/app_config_schema.py create mode 100644 nautobot_golden_config/app-config-schema.json diff --git a/.cookiecutter.json b/.cookiecutter.json index b19002e0..5d01c752 100644 --- a/.cookiecutter.json +++ b/.cookiecutter.json @@ -21,7 +21,7 @@ "_drift_manager": { "template": "https://github.com/nautobot/cookiecutter-nautobot-app.git", "template_dir": "nautobot-app", - "template_ref": "refs/tags/nautobot-app-v2.1.0", + "template_ref": "refs/tags/nautobot-app-v2.2.0", "cookie_dir": "", "branch_prefix": "drift-manager", "pull_request_strategy": "create", @@ -29,7 +29,7 @@ "black" ], "draft": true, - "baked_commit_ref": "c9dce46b70f0154a56974587202e71e82ef08bae" + "baked_commit_ref": "1f3e36613d3c301a807cdbdc4a90e849fd88c554" } } } diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 8a9b4cf1..7cf1631e 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -30,5 +30,4 @@ - [ ] Attached Screenshots, Payload Example - [ ] Unit, Integration Tests - [ ] Documentation Updates (when adding/changing features) -- [ ] Example App Updates (when adding/changing features) - [ ] Outline Remaining Work, Constraints from Design diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c128180..0f3c9bec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Linting: black" run: "poetry run invoke black" bandit: @@ -36,7 +36,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Linting: bandit" run: "poetry run invoke bandit" ruff: @@ -47,7 +47,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Linting: ruff" run: "poetry run invoke ruff" check-docs-build: @@ -58,7 +58,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Check Docs Build" run: "poetry run invoke build-and-check-docs" flake8: @@ -69,7 +69,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Linting: flake8" run: "poetry run invoke flake8" poetry: @@ -80,7 +80,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Checking: poetry lock file" run: "poetry run invoke lock --check" yamllint: @@ -91,10 +91,10 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Linting: yamllint" run: "poetry run invoke yamllint" - pylint: + check-in-docker: needs: - "bandit" - "ruff" @@ -115,7 +115,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Set up Docker Buildx" id: "buildx" uses: "docker/setup-buildx-action@v3" @@ -137,53 +137,13 @@ jobs: run: "cp development/creds.example.env development/creds.env" - name: "Linting: pylint" run: "poetry run invoke pylint" - check-migrations: - needs: - - "bandit" - - "ruff" - - "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_GOLDEN_CONFIG_PYTHON_VER: "${{ matrix.python-version }}" - INVOKE_NAUTOBOT_GOLDEN_CONFIG_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.APP_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: App Config" + run: "poetry run invoke validate-app-config" - name: "Checking: migrations" run: "poetry run invoke check-migrations" unittest: needs: - - "pylint" - - "check-migrations" + - "check-in-docker" strategy: fail-fast: true matrix: @@ -205,7 +165,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Set up Docker Buildx" id: "buildx" uses: "docker/setup-buildx-action@v3" @@ -241,7 +201,7 @@ jobs: with: fetch-depth: "0" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v4" + uses: "networktocode/gh-action-setup-poetry-environment@v6" - name: "Check for changelog entry" run: | git fetch --no-tags origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} @@ -258,7 +218,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Set up Python" - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "3.11" - name: "Install Python Packages" @@ -293,7 +253,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Set up Python" - uses: "actions/setup-python@v4" + uses: "actions/setup-python@v5" with: python-version: "3.11" - name: "Install Python Packages" diff --git a/changes/8.housekeeping b/changes/8.housekeeping new file mode 100644 index 00000000..653c54ac --- /dev/null +++ b/changes/8.housekeeping @@ -0,0 +1 @@ +Re-baked from the latest template. diff --git a/development/Dockerfile b/development/Dockerfile index 243db304..dbc52741 100644 --- a/development/Dockerfile +++ b/development/Dockerfile @@ -28,7 +28,7 @@ ENV INVOKE_NAUTOBOT_GOLDEN_CONFIG_LOCAL=true # 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 which poetry || curl -sSL https://install.python-poetry.org | python3 - && \ - poetry config virtualenvs.create false + poetry config virtualenvs.create false # !!! USE CAUTION WHEN MODIFYING LINES ABOVE # ------------------------------------------------------------------------------------- diff --git a/development/app_config_schema.py b/development/app_config_schema.py new file mode 100644 index 00000000..47009954 --- /dev/null +++ b/development/app_config_schema.py @@ -0,0 +1,64 @@ +"""App Config Schema Generator and Validator.""" +import json +from importlib import import_module +from os import getenv +from pathlib import Path +from urllib.parse import urlparse + +import jsonschema +import toml +from django.conf import settings +from to_json_schema.to_json_schema import SchemaBuilder + + +def _enrich_object_schema(schema, defaults, required): + schema["additionalProperties"] = False + for key, value in schema["properties"].items(): + if required and key in required: + value["required"] = True + default_value = defaults and defaults.get(key, None) + if value["type"] == "object" and "properties" in value: + _enrich_object_schema(value, default_value, None) + elif default_value is not None: + value["default"] = default_value + + +def _main(): + pyproject = toml.loads(Path("pyproject.toml").read_text()) + url = urlparse(pyproject["tool"]["poetry"]["repository"]) + _, owner, repository = url.path.split("/") + package_name = pyproject["tool"]["poetry"]["packages"][0]["include"] + app_config = settings.PLUGINS_CONFIG[package_name] # type: ignore + schema_path = Path(package_name) / "app-config-schema.json" + command = getenv("APP_CONFIG_SCHEMA_COMMAND", "") + if command == "generate": + schema = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": f"https://raw.githubusercontent.com/{owner}/{repository}/develop/{package_name}/app-config-schema.json", + "$comment": "TBD: Update $id, replace `develop` with the future release tag", + **SchemaBuilder().to_json_schema(app_config), # type: ignore + } + app_config = import_module(package_name).config + _enrich_object_schema(schema, app_config.default_settings, app_config.required_settings) + schema_path.write_text(json.dumps(schema, indent=4) + "\n") + print(f"\n==================\nGenerated schema:\n\n{schema_path}\n") + print( + "WARNING: Review and edit the generated file before committing.\n" + "\n" + "Its content is inferred from:\n" + "\n" + "- The current configuration in `PLUGINS_CONFIG`\n" + "- `NautobotAppConfig.default_settings`\n" + "- `NautobotAppConfig.required_settings`" + ) + elif command == "validate": + schema = json.loads(schema_path.read_text()) + jsonschema.validate(app_config, schema) + print( + f"\n==================\nValidated configuration using the schema:\n{schema_path}\nConfiguration is valid." + ) + else: + raise RuntimeError(f"Unknown command: {command}") + + +_main() diff --git a/development/nautobot_config.py b/development/nautobot_config.py index 29bafe35..776bcd4e 100644 --- a/development/nautobot_config.py +++ b/development/nautobot_config.py @@ -92,11 +92,11 @@ "disable_existing_loggers": False, "formatters": { "normal": { - "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)s :\n %(message)s", + "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)s : %(message)s", "datefmt": "%H:%M:%S", }, "verbose": { - "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-20s %(filename)-15s %(funcName)30s() :\n %(message)s", + "format": "%(asctime)s.%(msecs)03d %(levelname)-7s %(name)-20s %(filename)-15s %(funcName)30s() : %(message)s", "datefmt": "%H:%M:%S", }, }, diff --git a/development/towncrier_template.j2 b/development/towncrier_template.j2 index d2ec61bd..b0f6e12f 100644 --- a/development/towncrier_template.j2 +++ b/development/towncrier_template.j2 @@ -1,6 +1,6 @@ {% if render_title %} -## v{{ versiondata.version }} ({{ versiondata.date }}) +## [v{{ versiondata.version }} ({{ versiondata.date }})]({{ cookiecutter.repo_url }}/releases/tag/v{{ versiondata.version}}) {% endif %} {% for section, _ in sections.items() %} diff --git a/docs/admin/install.md b/docs/admin/install.md index 9a818399..49e4fdee 100644 --- a/docs/admin/install.md +++ b/docs/admin/install.md @@ -15,7 +15,7 @@ There are no access requirements from external systems to this app. ## Install Guide !!! note - Apps can be installed manually or using Python's `pip`. See the [nautobot documentation](https://nautobot.readthedocs.io/en/latest/plugins/#install-the-package) for more details. The pip package name for this app is [`nautobot-golden-config`](https://pypi.org/project/nautobot-golden-config/). + Apps can be installed from the [Python Package Index](https://pypi.org/) or locally. See the [Nautobot documentation](https://docs.nautobot.com/projects/core/en/stable/user-guide/administration/installation/app-install/) for more details. The pip package name for this app is [`nautobot-golden-config`](https://pypi.org/project/nautobot-golden-config/). The app is available as a Python package via PyPI and can be installed with `pip`: diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md index 4d074e31..81d39853 100644 --- a/docs/dev/contributing.md +++ b/docs/dev/contributing.md @@ -43,36 +43,30 @@ All pull requests to `next` or `develop` must include a changelog fragment file The branching policy includes the following tenets: -- The `develop` branch is the branch for bug fixes. -- The `next` branch is the branch for new features. -- The `stable-.` branch is the branch of the latest version within that major/minor version. -- The `stable-.` branch will have all of the latest bug fixes and security patches, and may or may not represent the released version. -- PRs intended to add new features should be branched from and merged to the `next` branch. -- PRs intended to add new features that break backward compatibility should be discussed before a PR is created. -- PRs intended to address bug fixes and security patches should be branched from and merged to the `develop` branch. +- The `develop` branch is the branch of the next major and minor paired version planned. +- PRs intended to add new features should be sourced from the `develop` branch. +- PRs intended to fix issues in the Nautobot LTM compatible release should be sourced from the latest `ltm-` branch instead of `develop`. -Nautobot Golden Config will observe semantic versioning, as of 1.0. This may result in an quick turn around in minor versions to keep pace with an ever growing feature set. +Golden Config will observe semantic versioning, as of 1.0. This may result in a quick turnaround in minor versions to keep pace with an ever growing feature set. ## Release Policy -Nautobot Golden Config has currently no intended scheduled release schedule, and will release new features in minor versions. +Golden Config has currently no intended scheduled release schedule, and will release new features in minor versions. -When a new release of any kind (e.g. from `develop` to `main`, or a release of a `stable-.`) is created the following should happen. +When a new release, from `develop` to `main`, is created the following should happen. -- A release PR is created: - - Add and/or update to the changelog in `docs/admin/release_notes/version_..md` file to reflect the changes. - - Update the mkdocs.yml file to include updates when adding a new release_notes version file. - - Change the version from `..-beta` to `..` in pyproject.toml. - - Set the PR to the proper branch, e.g. either `main` or `stable-.`. +- A release PR is created from `develop` with: + - Update the release notes in `docs/admin/release_notes/version_..md` file to reflect the changes. + - Change the version from `..-beta` to `..` in `pyproject.toml`. + - Set the PR to the `main` branch. - Ensure the tests for the PR pass. - Merge the PR. - Create a new tag: - - The tag should be in the form of `v..`. - - The title should be in the form of `v..`. - - The description should be the changes that were added to the `version_..md` document. -- If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged. -- If the is a new `.`, create a `stable-.` for the **previous** version, so that security updates to old versions may be applied more easily. -- A post release PR is created: - - Change the version from `..` to `..-beta` in pyproject.toml. - - Set the PR to the proper branch, e.g. either `develop` or `stable-.`. - - Once tests pass, merge. + - The tag should be in the form of `v..`. + - The title should be in the form of `v..`. + - The description should be the changes that were added to the `version_..md` document. +- If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged +- A post release PR is created with: + - Change the version from `..` to `..-beta` in both `pyproject.toml` and `nautobot.__init__.__version__`. + - Set the PR to the proper branch, `develop`. + - Once tests pass, merge. diff --git a/docs/dev/dev_environment.md b/docs/dev/dev_environment.md index 8ff0c27d..95837814 100644 --- a/docs/dev/dev_environment.md +++ b/docs/dev/dev_environment.md @@ -74,7 +74,7 @@ nautobot-server migrate !!! note If you want to develop on the latest develop branch of Nautobot, run the following command: `poetry add --optional git+https://github.com/nautobot/nautobot@develop`. After the `@` symbol must match either a branch or a tag. -You can now run `nautobot-server` commands as you would from the [Nautobot documentation](https://nautobot.readthedocs.io/en/latest/) for example to start the development server: +You can now run `nautobot-server` commands as you would from the [Nautobot documentation](https://docs.nautobot.com/projects/core/en/stable/user-guide/administration/tools/nautobot-server/) for example to start the development server: ```shell nautobot-server runserver 0.0.0.0:8080 --insecure @@ -470,3 +470,21 @@ To run an individual test, you can run any or all of the following: ➜ invoke ruff ➜ invoke pylint ``` + +### App Configuration Schema + +In the package source, there is the `nautobot_golden_config/app-config-schema.json` file, conforming to the [JSON Schema](https://json-schema.org/) format. This file is used to validate the configuration of the app in CI pipelines. + +If you make changes to `PLUGINS_CONFIG` or the configuration schema, you can run the following command to validate the schema: + +```bash +invoke validate-app-config +``` + +To generate the `app-config-schema.json` file based on the current `PLUGINS_CONFIG` configuration, run the following command: + +```bash +invoke generate-app-config-schema +``` + +This command can only guess the schema, so it's up to the developer to manually update the schema as needed. diff --git a/mkdocs.yml b/mkdocs.yml index f08d1492..6fa13912 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -81,7 +81,11 @@ markdown_extensions: anchor_linenums: true - "pymdownx.inlinehilite" - "pymdownx.snippets" - - "pymdownx.superfences" + - "pymdownx.superfences": + custom_fences: + - name: "mermaid" + class: "mermaid" + format: !!python/name:pymdownx.superfences.fence_code_format - "footnotes" plugins: - "search" diff --git a/nautobot_golden_config/app-config-schema.json b/nautobot_golden_config/app-config-schema.json new file mode 100644 index 00000000..27ba77dd --- /dev/null +++ b/nautobot_golden_config/app-config-schema.json @@ -0,0 +1 @@ +true diff --git a/poetry.lock b/poetry.lock index ed134e5b..63c09da1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "amqp" @@ -4418,6 +4418,20 @@ files = [ future = "*" six = "*" +[[package]] +name = "to-json-schema" +version = "1.0.1" +description = "" +optional = false +python-versions = "*" +files = [ + {file = "to_json_schema-1.0.1-py3-none-any.whl", hash = "sha256:5708663f1c81815e4ff01fce910ac32ee3964d0c6b3587fd4fff2e38d5c9aa7b"}, + {file = "to_json_schema-1.0.1.tar.gz", hash = "sha256:ec747bd5129256dd571105f66a7bc9a4546228cd5e5fbf5e06dc9776e255400e"}, +] + +[package.extras] +testing = ["pytest", "pytest-cov", "setuptools"] + [[package]] name = "toml" version = "0.10.2" @@ -4785,4 +4799,4 @@ all = [] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "f1896597c9887054c25a28518d6a5dbb9201c6a4f97920a953964a5dc33b363e" +content-hash = "2501da506f0545bd3c3000d3004ca3b46720d3233fa59e3b7b0b80c902d24cc4" diff --git a/pyproject.toml b/pyproject.toml index 2c10704b..d9ee991e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,6 +66,8 @@ mkdocs-version-annotations = "1.0.0" mkdocstrings = "0.22.0" mkdocstrings-python = "1.5.2" towncrier = "~23.6.0" +to-json-schema = "*" +jsonschema = "*" [tool.poetry.extras] all = [ @@ -171,7 +173,7 @@ requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.towncrier] -package = "nautobot" +package = "nautobot_golden_config" directory = "changes" filename = "docs/admin/release_notes/version_X.Y.md" template = "development/towncrier_template.j2" diff --git a/tasks.py b/tasks.py index d620399a..09bc977f 100644 --- a/tasks.py +++ b/tasks.py @@ -149,15 +149,27 @@ def docker_compose(context, command, **kwargs): def run_command(context, command, **kwargs): """Wrapper to run a command locally or inside the nautobot container.""" if is_truthy(context.nautobot_golden_config.local): + if "command_env" in kwargs: + kwargs["env"] = { + **kwargs.get("env", {}), + **kwargs.pop("command_env"), + } context.run(command, **kwargs) else: # Check if nautobot is running, no need to start another nautobot container to run a command docker_compose_status = "ps --services --filter status=running" results = docker_compose(context, docker_compose_status, hide="out") if "nautobot" in results.stdout: - compose_command = f"exec nautobot {command}" + compose_command = "exec" else: - compose_command = f"run --rm --entrypoint '{command}' nautobot" + compose_command = "run --rm --entrypoint=''" + + if "command_env" in kwargs: + command_env = kwargs.pop("command_env") + for key, value in command_env.items(): + compose_command += f' --env="{key}={value}"' + + compose_command += f" -- nautobot {command}" pty = kwargs.pop("pty", True) @@ -327,15 +339,22 @@ def logs(context, service="", follow=False, tail=0): # ------------------------------------------------------------------------------ # ACTIONS # ------------------------------------------------------------------------------ -@task(help={"file": "Python file to execute"}) -def nbshell(context, file=""): +@task( + help={ + "file": "Python file to execute", + "env": "Environment variables to pass to the command", + "plain": "Flag to run nbshell in plain mode (default: False)", + }, +) +def nbshell(context, file="", env={}, plain=False): """Launch an interactive nbshell session.""" command = [ "nautobot-server", "nbshell", + "--plain" if plain else "", f"< '{file}'" if file else "", ] - run_command(context, " ".join(command), pty=not bool(file)) + run_command(context, " ".join(command), pty=not bool(file), command_env=env) @task @@ -798,8 +817,33 @@ def tests(context, failfast=False, keepdb=False, lint_only=False): pylint(context) print("Running mkdocs...") build_and_check_docs(context) + print("Checking app config schema...") + validate_app_config(context) if not lint_only: print("Running unit tests...") unittest(context, failfast=failfast, keepdb=keepdb) unittest_coverage(context) print("All tests have passed!") + + +@task +def generate_app_config_schema(context): + """Generate the app config schema from the current app config. + + WARNING: Review and edit the generated file before committing. + + Its content is inferred from: + + - The current configuration in `PLUGINS_CONFIG` + - `NautobotAppConfig.default_settings` + - `NautobotAppConfig.required_settings` + """ + start(context, service="nautobot") + nbshell(context, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "generate"}) + + +@task +def validate_app_config(context): + """Validate the app config based on the app config schema.""" + start(context, service="nautobot") + nbshell(context, plain=True, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "validate"}) From 508e00cbae595285b4ad4082e03a9ae029750a54 Mon Sep 17 00:00:00 2001 From: Jeff Kala <48843785+jeffkala@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:28:27 -0600 Subject: [PATCH 12/17] fix #731 missing right panel with config types (#732) * fix #731 missing right panel with config types --- changes/731.fixed | 1 + .../content_template.html | 236 +++++++++--------- 2 files changed, 119 insertions(+), 118 deletions(-) create mode 100755 changes/731.fixed diff --git a/changes/731.fixed b/changes/731.fixed new file mode 100755 index 00000000..90daa725 --- /dev/null +++ b/changes/731.fixed @@ -0,0 +1 @@ +Fixed missing config-types panel content on device detail view. diff --git a/nautobot_golden_config/templates/nautobot_golden_config/content_template.html b/nautobot_golden_config/templates/nautobot_golden_config/content_template.html index 879ca4d6..813f31aa 100644 --- a/nautobot_golden_config/templates/nautobot_golden_config/content_template.html +++ b/nautobot_golden_config/templates/nautobot_golden_config/content_template.html @@ -1,124 +1,124 @@ {% if compliance %} -
- {% if template_type == "devicetab" %} - -
- - - - - - - - - {% for item in compliance %} - - - - - {% endfor %} - -
FeatureCompliance
{{ item.rule__feature__name }} - {% if item.compliance == False %} - Non-Compliant - {% elif item.compliance == True %} - Compliant - {% else %} - N/A - {% endif %} -
-
- {% endif %} {% if template_type == 'location' %}
- - - - - - - - - - {% for item in compliance %} - - - - - - {% endfor %} - -
FeatureNon-compliantCompliant
{{ item.rule__feature__name }}{{ item.non_compliant }}{{ item.compliant }}
-
- {% endif %} {% if template_type == "device-configs" %} -
- Configuration Types + {% if template_type == "devicetab" %} + +
+ + + + + + + + + {% for item in compliance %} + + + + + {% endfor %} + +
FeatureCompliance
{{ item.rule__feature__name }} + {% if item.compliance == False %} + Non-Compliant + {% elif item.compliance == True %} + Compliant + {% else %} + N/A + {% endif %} +
+
+ {% elif template_type == 'location' %} +
+ + + + + + + + + + {% for item in compliance %} + + + + + + {% endfor %} + +
FeatureNon-compliantCompliant
{{ item.rule__feature__name }}{{ item.non_compliant }}{{ item.compliant }}
+
+ {% endif %}
+{% endif %} +{# The panel will not show up, since it is returned early in template_content.py based on an actual GoldenConfig object existing #} +{% if template_type == "device-configs" %}
- - - - - - - - - {% if config_features.compliance and golden_config.compliance_config %} - - - - - {% endif %} {% if config_features.intended and golden_config.intended_config %} - - - - - {% endif %} {% if config_features.postprocessing and golden_config.intended_config %} - - - - - {% endif %} {% if config_features.backup and golden_config.backup_config %} - - - - - {% endif %} {% if config_features.sotagg %} - - - - - {% endif %} - -
TypeConfig
Compliance - -
Intended - -
Configuration Postprocessing - -
Actual - -
SoT Aggregation Data - -
+
+ Configuration Types +
+
+ + + + + + + + + {% if config_features.compliance and golden_config.compliance_config %} + + + + + {% endif %} {% if config_features.intended and golden_config.intended_config %} + + + + + {% endif %} {% if config_features.postprocessing and golden_config.intended_config %} + + + + + {% endif %} {% if config_features.backup and golden_config.backup_config %} + + + + + {% endif %} {% if config_features.sotagg %} + + + + + {% endif %} + +
TypeConfig
Compliance + + + +
Intended + + + +
Configuration Postprocessing + + + +
Actual + + + +
SoT Aggregation Data + + + +
+
- {% endif %} -
{% endif %} \ No newline at end of file From cc87d64e9421d32bda7300ebb1e6987bbb463f2b Mon Sep 17 00:00:00 2001 From: Allen Hogan <98360253+alhogan@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:28:51 -0500 Subject: [PATCH 13/17] Use "netutils_parser" instead of "netmiko" for parser lookup (#734) --- nautobot_golden_config/nornir_plays/config_compliance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nautobot_golden_config/nornir_plays/config_compliance.py b/nautobot_golden_config/nornir_plays/config_compliance.py index bb3ad3c5..af511b4c 100644 --- a/nautobot_golden_config/nornir_plays/config_compliance.py +++ b/nautobot_golden_config/nornir_plays/config_compliance.py @@ -64,12 +64,12 @@ def get_config_element(rule, config, obj, logger): config_element = config_json elif rule["obj"].config_type == ComplianceRuleConfigTypeChoice.TYPE_CLI: - if obj.platform.network_driver_mappings["netmiko"] not in parser_map: + if obj.platform.network_driver_mappings["netutils_parser"] not in parser_map: error_msg = f"`E3003:` There is currently no CLI-config parser support for platform network_driver `{obj.platform.network_driver}`, preemptively failed." logger.error(error_msg, extra={"object": obj}) raise NornirNautobotException(error_msg) - config_element = section_config(rule, config, obj.platform.network_driver_mappings["netmiko"]) + config_element = section_config(rule, config, obj.platform.network_driver_mappings["netutils_parser"]) else: error_msg = f"`E3004:` There rule type ({rule['obj'].config_type}) is not recognized." From 173b48830aa478b56b64c2240cf87124d5200a61 Mon Sep 17 00:00:00 2001 From: itdependsnetworks Date: Sat, 9 Mar 2024 08:25:37 -0500 Subject: [PATCH 14/17] Prep 2.0.2 release --- changes/692.added | 1 - changes/692.changed | 1 - changes/692.fixed | 2 -- changes/707.changed | 1 - changes/8.housekeeping | 1 - docs/admin/release_notes/version_2.0.md | 27 +++++++++++++++++++++++-- docs/dev/contributing.md | 19 ++++++++--------- pyproject.toml | 2 +- 8 files changed, 36 insertions(+), 18 deletions(-) delete mode 100755 changes/692.added delete mode 100755 changes/692.changed delete mode 100755 changes/692.fixed delete mode 100644 changes/707.changed delete mode 100644 changes/8.housekeeping diff --git a/changes/692.added b/changes/692.added deleted file mode 100755 index a38f2294..00000000 --- a/changes/692.added +++ /dev/null @@ -1 +0,0 @@ -Add multiple new unittest test classes to validate repo syncing, commiting, and pushing logic. diff --git a/changes/692.changed b/changes/692.changed deleted file mode 100755 index e5a1c980..00000000 --- a/changes/692.changed +++ /dev/null @@ -1 +0,0 @@ -Changed QuerySet and device_to_settings map into new decorator to run only one time instead of multiple. diff --git a/changes/692.fixed b/changes/692.fixed deleted file mode 100755 index 2d2f42e7..00000000 --- a/changes/692.fixed +++ /dev/null @@ -1,2 +0,0 @@ -Fixed performance issue on UNIX file diff view by reverting back to readlines(). -Fixed non-working repos list creation and syncing from run method to new decorator. diff --git a/changes/707.changed b/changes/707.changed deleted file mode 100644 index 7a7cdde0..00000000 --- a/changes/707.changed +++ /dev/null @@ -1 +0,0 @@ -Replaced pydocstyle with ruff. diff --git a/changes/8.housekeeping b/changes/8.housekeeping deleted file mode 100644 index 653c54ac..00000000 --- a/changes/8.housekeeping +++ /dev/null @@ -1 +0,0 @@ -Re-baked from the latest template. diff --git a/docs/admin/release_notes/version_2.0.md b/docs/admin/release_notes/version_2.0.md index 81a2a53a..994a18ad 100755 --- a/docs/admin/release_notes/version_2.0.md +++ b/docs/admin/release_notes/version_2.0.md @@ -11,6 +11,29 @@ !!! note Please see [migrating guide](../migrating_to_v2.md) for details on migration. +## v2.0.2 - 2024-03 + +### Added + +- [#707](https://github.com/nautobot/nautobot-app-golden-config/pull/707) - Added autoformat invoke command. +- [#730](https://github.com/nautobot/nautobot-app-golden-config/pull/730) - Added app config schema generator and validator. + +### Fixed + +- [#699](https://github.com/nautobot/nautobot-app-golden-config/pull/699) - Fixed stale reference to platform_slug_map. +- [#719](https://github.com/nautobot/nautobot-app-golden-config/pull/719) - Fixed generate config plans Status filter. +- [#715](https://github.com/nautobot/nautobot-app-golden-config/pull/715) - Fixed close threaded db connections during config deployment. +- [#726](https://github.com/nautobot/nautobot-app-golden-config/pull/726) - Fixed objectchange log excludes for object_data_v2 data as well. +- [#718](https://github.com/nautobot/nautobot-app-golden-config/pull/718) - Fixed logic to handle jobs requiring approvals. +- [#724](https://github.com/nautobot/nautobot-app-golden-config/pull/724) - Fixed performance issue on UNIX file diff view. +- [#724](https://github.com/nautobot/nautobot-app-golden-config/pull/724) - Fixed non-working repos list creation and syncing. +- [#731](https://github.com/nautobot/nautobot-app-golden-config/pull/731) - Fixed missing right panel with config types. + +### Changed + +- [#691](https://github.com/nautobot/nautobot-app-golden-config/pull/691) - Changed repo name and references to nautobot-app-golden-config. +- [#707](https://github.com/nautobot/nautobot-app-golden-config/pull/707) - Changed from pydocstyle to ruff. +- [#707](https://github.com/nautobot/nautobot-app-golden-config/pull/707) - Changed release notes to towncrier based. ## v2.0.1 - 2023-12 @@ -25,8 +48,8 @@ ### Changed -- [#658](https://github.com/nautobot/nautobot-app-golden-config/pull/658) - Cookie updated by NetworkToCode Cookie Drift Manager Tool -- [#671](https://github.com/nautobot/nautobot-app-golden-config/pull/671) - Finish Documentation Updates from Drift Manager +- [#658](https://github.com/nautobot/nautobot-app-golden-config/pull/658) - Cookie updated by NetworkToCode Cookie Drift Manager Tool. +- [#671](https://github.com/nautobot/nautobot-app-golden-config/pull/671) - Finish Documentation Updates from Drift Manager. ## v2.0.0 - 2023-09 diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md index 81d39853..f7d05f83 100644 --- a/docs/dev/contributing.md +++ b/docs/dev/contributing.md @@ -56,17 +56,18 @@ Golden Config has currently no intended scheduled release schedule, and will rel When a new release, from `develop` to `main`, is created the following should happen. - A release PR is created from `develop` with: - - Update the release notes in `docs/admin/release_notes/version_..md` file to reflect the changes. - - Change the version from `..-beta` to `..` in `pyproject.toml`. - - Set the PR to the `main` branch. + - Update the release notes in `docs/admin/release_notes/version_..md` file to reflect the changes. + - Update the mkdocs.yml file to include the reference to `docs/admin/release_notes/version_..md` as applicable. + - Change the version from `..-beta` to `..` in `pyproject.toml`. + - Set the PR to the `main` branch. - Ensure the tests for the PR pass. - Merge the PR. - Create a new tag: - - The tag should be in the form of `v..`. - - The title should be in the form of `v..`. - - The description should be the changes that were added to the `version_..md` document. + - The tag should be in the form of `v..`. + - The title should be in the form of `v..`. + - The description should be the changes that were added to the `version_..md` document. - If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged - A post release PR is created with: - - Change the version from `..` to `..-beta` in both `pyproject.toml` and `nautobot.__init__.__version__`. - - Set the PR to the proper branch, `develop`. - - Once tests pass, merge. + - Change the version from `..` to `..-beta` in `pyproject.toml`. + - Set the PR to the proper branch, `develop`. + - Once tests pass, merge. diff --git a/pyproject.toml b/pyproject.toml index d9ee991e..6581c770 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nautobot-golden-config" -version = "2.0.0" +version = "2.0.2" description = "An app for configuration on nautobot" authors = ["Network to Code, LLC "] license = "Apache-2.0" From 9792ba29047f5cb8d4ce86fb5078d78813a0478d Mon Sep 17 00:00:00 2001 From: itdependsnetworks Date: Sat, 9 Mar 2024 13:18:47 -0500 Subject: [PATCH 15/17] Update release docs --- docs/dev/contributing.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md index f7d05f83..5716d338 100644 --- a/docs/dev/contributing.md +++ b/docs/dev/contributing.md @@ -53,21 +53,26 @@ Golden Config will observe semantic versioning, as of 1.0. This may result in a Golden Config has currently no intended scheduled release schedule, and will release new features in minor versions. -When a new release, from `develop` to `main`, is created the following should happen. +When a release is ready to be created from either `develop` or `ltm-x.x`, the following should happen. -- A release PR is created from `develop` with: +- Create a release PR by: + - Source from `develop` or `ltm-.` branch and creatch new branch, generally `release/..`. - Update the release notes in `docs/admin/release_notes/version_..md` file to reflect the changes. + - You can run `invoke generate-release-notes` to generate these notes and delete the legacy towncrier fragments. + - Please consider adding changelog's from ltm releases in current release, as applicable. - Update the mkdocs.yml file to include the reference to `docs/admin/release_notes/version_..md` as applicable. - Change the version from `..-beta` to `..` in `pyproject.toml`. - - Set the PR to the `main` branch. + - Set the PR to the `main` or `ltm-.` branch respectivly. - Ensure the tests for the PR pass. - Merge the PR. - Create a new tag: - The tag should be in the form of `v..`. - The title should be in the form of `v..`. - The description should be the changes that were added to the `version_..md` document. + - Include full changelog in description `**Full Changelog**: https://github.com/nautobot//compare/v...v`. + - **Note** Please ensure to uncheck `Set as the latest release` when updating an ltm release. - If merged into `main`, then push from `main` to `develop`, in order to retain the merge commit created when the PR was merged - A post release PR is created with: - Change the version from `..` to `..-beta` in `pyproject.toml`. - Set the PR to the proper branch, `develop`. - - Once tests pass, merge. + - Once tests pass, merge. \ No newline at end of file From 22f8bbda9d3e16ae22e26223bc7581ebc684c803 Mon Sep 17 00:00:00 2001 From: itdependsnetworks Date: Sat, 9 Mar 2024 13:19:34 -0500 Subject: [PATCH 16/17] Update release docs --- docs/dev/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md index 5716d338..3c3dd43a 100644 --- a/docs/dev/contributing.md +++ b/docs/dev/contributing.md @@ -62,7 +62,7 @@ When a release is ready to be created from either `develop` or `ltm-x.x`, the fo - Please consider adding changelog's from ltm releases in current release, as applicable. - Update the mkdocs.yml file to include the reference to `docs/admin/release_notes/version_..md` as applicable. - Change the version from `..-beta` to `..` in `pyproject.toml`. - - Set the PR to the `main` or `ltm-.` branch respectivly. + - Set the PR to the `main` or `ltm-.` branch respectively. - Ensure the tests for the PR pass. - Merge the PR. - Create a new tag: From 16ea6013a2aa97e3cf0a18fffec4874a404097ef Mon Sep 17 00:00:00 2001 From: itdependsnetworks Date: Mon, 11 Mar 2024 13:32:06 -0400 Subject: [PATCH 17/17] update release notes --- changes/731.fixed | 1 - docs/admin/release_notes/version_2.0.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100755 changes/731.fixed diff --git a/changes/731.fixed b/changes/731.fixed deleted file mode 100755 index 90daa725..00000000 --- a/changes/731.fixed +++ /dev/null @@ -1 +0,0 @@ -Fixed missing config-types panel content on device detail view. diff --git a/docs/admin/release_notes/version_2.0.md b/docs/admin/release_notes/version_2.0.md index 994a18ad..19455831 100755 --- a/docs/admin/release_notes/version_2.0.md +++ b/docs/admin/release_notes/version_2.0.md @@ -28,6 +28,7 @@ - [#724](https://github.com/nautobot/nautobot-app-golden-config/pull/724) - Fixed performance issue on UNIX file diff view. - [#724](https://github.com/nautobot/nautobot-app-golden-config/pull/724) - Fixed non-working repos list creation and syncing. - [#731](https://github.com/nautobot/nautobot-app-golden-config/pull/731) - Fixed missing right panel with config types. +- [#734](https://github.com/nautobot/nautobot-app-golden-config/pull/734) - Fixed incorrect netutils_parser lookup. ### Changed