Skip to content

Commit

Permalink
update docs, code cleanup, changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
gsnider2195 committed Dec 9, 2024
1 parent 5301252 commit 4052821
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 18 deletions.
1 change: 1 addition & 0 deletions changes/844.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a diff output to the "Generate Intended Config" view and associated REST API.
Binary file modified docs/images/generate-intended-config-ui-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/generate-intended-config-ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion docs/user/app_feature_intended.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ curl -s -X GET \
http://nautobot/api/plugins/golden-config/generate-intended-config/?device_id=231b8765-054d-4abe-bdbf-cd60e049cd8d
```

The returned response will contain the rendered configuration for the specified device and the GraphQL data that was used. The web UI provides a simple form to input the device and displays the rendered configuration when submitted.
The returned response will contain the rendered configuration for the specified device, the GraphQL data that was used, and if applicable, a diff of the most recent intended config that was generated by the **Intended Configuration** job. The web UI provides a simple form to interact with this REST API. You can access the web UI by clicking on "Generate Intended Config" in the "Tools" section of the Golden Config navigation menu.

For more advanced use cases, the REST API and web UI also accept a `graphql_query_id` parameter to specify a custom GraphQL query to use when rendering the configuration. If a `graphql_query_id` is not provided, the default query configured in the Device's Golden Config settings will be used.

![Intended Configuration Web UI](../images/generate-intended-config-ui.png#only-light)
![Intended Configuration Web UI](../images/generate-intended-config-ui-dark.png#only-dark)
Expand Down
36 changes: 21 additions & 15 deletions nautobot_golden_config/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,26 @@ class GenerateIntendedConfigView(NautobotAPIVersionMixin, GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = serializers.GenerateIntendedConfigSerializer

def _get_diff(self, device, intended_config):
"""Generate a unified diff between the provided config and the intended config stored on the Device's GoldenConfig.intended_config."""
diff = None
try:
golden_config = device.goldenconfig
if golden_config.intended_last_success_date is not None:
prior_intended_config = golden_config.intended_config
diff = "".join(
difflib.unified_diff(
prior_intended_config.splitlines(keepends=True),
intended_config.splitlines(keepends=True),
fromfile="prior intended config",
tofile="rendered config",
)
)
except models.GoldenConfig.DoesNotExist:
pass

return diff

def _get_object(self, request, model, query_param):
"""Get the requested model instance, restricted to requesting user."""
pk = request.query_params.get(query_param)
Expand Down Expand Up @@ -289,21 +309,7 @@ def get(self, request, *args, **kwargs):
except Exception as exc:
raise GenerateIntendedConfigException(f"Error rendering Jinja template: {exc}") from exc

diff = None
try:
golden_config = device.goldenconfig
if golden_config.intended_last_success_date is not None:
prior_intended_config = golden_config.intended_config
diff = "".join(
difflib.unified_diff(
prior_intended_config.splitlines(keepends=True),
intended_config.splitlines(keepends=True),
fromfile="prior intended config",
tofile="rendered config",
)
)
except Device.goldenconfig.RelatedObjectDoesNotExist:
pass
diff = self._get_diff(device, intended_config)

return Response(
data={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
.d2h-tag {
display: none;
}
.d2h-file-collapse {
display:none;
.d2h-file-name {
visibility: hidden;
}
.d2h-moved {
visibility: hidden;
}
.d2h-file-list-title {
display: none;
}
.button-container {
margin-bottom: 24px;
Expand Down Expand Up @@ -193,6 +199,9 @@
// render the diff
if (responseData.diff == null) {
diff_render_div.innerHTML = "<p>No intended configuration available to diff against. You may need to run the intended configuration job first.</p>";
// output a message if no diff
} else if (responseData.diff === "") {
diff_render_div.innerHTML = "<p>No changes detected.</p>";
} else {
diff_render_div.innerHTML = Diff2Html.html(responseData.diff, {
drawFileList: true,
Expand Down

0 comments on commit 4052821

Please sign in to comment.