Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement plan_result and deploy_result #594

Merged
merged 5 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions nautobot_golden_config/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,9 +424,13 @@ class ConfigPlanFilterSet(NautobotFilterSet):
to_field_name="name",
label="Feature Name",
)
job_result_id = django_filters.ModelMultipleChoiceFilter(
plan_result_id = django_filters.ModelMultipleChoiceFilter(
queryset=JobResult.objects.filter(config_plan__isnull=False).distinct(),
label="JobResult ID",
label="Plan JobResult ID",
)
deploy_result_id = django_filters.ModelMultipleChoiceFilter(
queryset=JobResult.objects.filter(config_plan__isnull=False).distinct(),
label="Deploy JobResult ID",
)
change_control_id = django_filters.CharFilter(
field_name="change_control_id",
Expand Down
11 changes: 9 additions & 2 deletions nautobot_golden_config/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,17 @@ class ConfigPlanFilterForm(NautobotFilterForm):
to_field_name="name",
)
change_control_id = forms.CharField(required=False, label="Change Control ID")
job_result_id = utilities_forms.DynamicModelMultipleChoiceField(
plan_result_id = utilities_forms.DynamicModelMultipleChoiceField(
queryset=JobResult.objects.all(),
query_params={"nautobot_golden_config_config_plan_null": True},
label="Job Result",
label="Plan Result",
required=False,
display_field="id",
)
deploy_result_id = utilities_forms.DynamicModelMultipleChoiceField(
queryset=JobResult.objects.all(),
query_params={"nautobot_golden_config_config_plan_null": True},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
query_params={"nautobot_golden_config_config_plan_null": True},
query_params={"nautobot_golden_config_config_plan_deploy_result_null": True},

I think this needs to be the related name? Double check me on this.

label="Deploy Result",
required=False,
display_field="id",
)
Expand Down
4 changes: 2 additions & 2 deletions nautobot_golden_config/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def _generate_config_plan_from_feature(self):
change_control_id=self._change_control_id,
change_control_url=self._change_control_url,
status=self._status,
job_result=self.job_result,
plan_result=self.job_result,
)
config_plan.feature.set(features)
config_plan.validated_save()
Expand All @@ -325,7 +325,7 @@ def _generate_config_plan_from_manual(self):
change_control_id=self._change_control_id,
change_control_url=self._change_control_url,
status=self._status,
job_result=self.job_result,
plan_result=self.job_result,
)
self.log_success(obj=config_plan, message=f"Config plan created for {device} with manual commands.")

Expand Down
22 changes: 0 additions & 22 deletions nautobot_golden_config/migrations/0027_auto_20230912_1731.py

This file was deleted.

40 changes: 40 additions & 0 deletions nautobot_golden_config/migrations/0027_auto_20230915_1657.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 3.2.20 on 2023-09-15 16:57

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
dependencies = [
("extras", "0058_jobresult_add_time_status_idxs"),
("nautobot_golden_config", "0026_configplan"),
]

operations = [
migrations.AlterModelOptions(
name="remediationsetting",
options={"ordering": ("platform", "remediation_type")},
),
migrations.RenameField(
model_name="configplan",
old_name="job_result",
new_name="plan_result",
),
migrations.AddField(
model_name="configplan",
name="deploy_result",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="config_plan_deploy_result",
to="extras.jobresult",
),
),
migrations.AlterField(
model_name="configplan",
name="change_control_id",
field=models.CharField(blank=True, default="", max_length=50),
preserve_default=False,
),
]
13 changes: 11 additions & 2 deletions nautobot_golden_config/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from nautobot.utilities.utils import serialize_object, serialize_object_v2
from netutils.config.compliance import feature_compliance
from netutils.lib_mapper import HIERCONFIG_LIB_MAPPER_REVERSE

from nautobot_golden_config.choices import ComplianceRuleConfigTypeChoice, ConfigPlanTypeChoice, RemediationTypeChoice
from nautobot_golden_config.utilities.constant import ENABLE_SOTAGG, PLUGIN_CFG
from nautobot_golden_config.utilities.utils import get_platform
Expand Down Expand Up @@ -865,11 +866,19 @@ class ConfigPlan(PrimaryModel): # pylint: disable=too-many-ancestors
related_name="config_plan",
blank=True,
)
job_result = models.ForeignKey(
plan_result = models.ForeignKey(
to="extras.JobResult",
on_delete=models.CASCADE,
related_name="config_plan",
verbose_name="Job Result",
verbose_name="Plan Result",
)
deploy_result = models.ForeignKey(
to="extras.JobResult",
on_delete=models.PROTECT,
related_name="config_plan_deploy_result",
verbose_name="Deploy Result",
blank=True,
null=True,
)
change_control_id = models.CharField(
max_length=50,
Expand Down
7 changes: 5 additions & 2 deletions nautobot_golden_config/nornir_plays/config_deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory)


def run_deployment(task: Task, logger: NornirLogger, commit: bool, config_plan_qs) -> Result:
def run_deployment(task: Task, logger: NornirLogger, commit: bool, config_plan_qs, deploy_job_result) -> Result:
"""Deploy configurations to device."""
obj = task.host.data["obj"]
plans_to_deploy = config_plan_qs.filter(device=obj)
plans_to_deploy.update(deploy_result=deploy_job_result.job_result)
consolidated_config_set = "\n".join(plans_to_deploy.values_list("config_set", flat=True))
logger.log_debug(f"Consolidated config set: {consolidated_config_set}")
# TODO: We should add post-processing rendering here
Expand Down Expand Up @@ -67,7 +68,8 @@ def config_deployment(job_result, data, commit):
now = datetime.now()
logger = NornirLogger(__name__, job_result, data.get("debug"))
logger.log_debug("Starting config deployment")

logger.log_debug(f"{dir(job_result)}")
logger.log_debug(f"{type(job_result)}")
config_plan_qs = data["config_plan"]
if config_plan_qs.filter(status__slug="not-approved").exists():
logger.log_failure(
Expand Down Expand Up @@ -99,6 +101,7 @@ def config_deployment(job_result, data, commit):
logger=logger,
commit=commit,
config_plan_qs=config_plan_qs,
deploy_job_result=job_result,
)
except Exception as err:
logger.log_failure(obj=None, message=f"Failed to initialize Nornir: {err}")
Expand Down
35 changes: 18 additions & 17 deletions nautobot_golden_config/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,11 @@
from django.utils.html import format_html
from django_tables2 import Column, LinkColumn, TemplateColumn
from django_tables2.utils import A

from nautobot.extras.tables import StatusTableMixin
from nautobot.utilities.tables import (
BaseTable,
ToggleColumn,
TagColumn,
)
from nautobot_golden_config import models
from nautobot_golden_config.utilities.constant import (
ENABLE_BACKUP,
ENABLE_COMPLIANCE,
ENABLE_INTENDED,
CONFIG_FEATURES,
)
from nautobot.utilities.tables import BaseTable, TagColumn, ToggleColumn

from nautobot_golden_config import models
from nautobot_golden_config.utilities.constant import CONFIG_FEATURES, ENABLE_BACKUP, ENABLE_COMPLIANCE, ENABLE_INTENDED

ALL_ACTIONS = """
{% if backup == True %}
Expand Down Expand Up @@ -496,8 +486,17 @@ class ConfigPlanTable(StatusTableMixin, BaseTable):

pk = ToggleColumn()
device = LinkColumn("plugins:nautobot_golden_config:configplan", args=[A("pk")])
job_result = TemplateColumn(
template_code="""<a href="{% url 'extras:jobresult' pk=record.job_result.pk %}" <i class="mdi mdi-clipboard-text-play-outline"></i></a> """
plan_result = TemplateColumn(
template_code="""<a href="{% url 'extras:jobresult' pk=record.plan_result.pk %}" <i class="mdi mdi-clipboard-text-play-outline"></i></a> """
)
deploy_result = TemplateColumn(
template_code="""
{% if record.deploy_result %}
<a href="{% url 'extras:jobresult' pk=record.deploy_result.pk %}" <i class="mdi mdi-clipboard-text-play-outline"></i></a>
{% else %}
&mdash;
{% endif %}
"""
)
config_set = TemplateColumn(template_code=CONFIG_SET_BUTTON, verbose_name="Config Set", orderable=False)
tags = TagColumn(url_name="plugins:nautobot_golden_config:configplan_list")
Expand All @@ -514,7 +513,8 @@ class Meta(BaseTable.Meta):
"feature",
"change_control_id",
"change_control_url",
"job_result",
"plan_result",
"deploy_result",
"config_set",
"status",
"tags",
Expand All @@ -527,7 +527,8 @@ class Meta(BaseTable.Meta):
"feature",
"change_control_id",
"change_control_url",
"job_result",
"plan_result",
"deploy_result",
"config_set",
"status",
)
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

function configPlanCount(jobResultId) {
return new Promise(function(resolve, reject) {
var configPlanApi = `/api/plugins/golden-config/config-plan/?job_result_id=${jobResultId}`;
var configPlanApi = `/api/plugins/golden-config/config-plan/?plan_result_id=${jobResultId}`;
$.ajax({
url: configPlanApi,
type: "GET",
Expand Down Expand Up @@ -108,7 +108,7 @@
}

var jobClass = "plugins/nautobot_golden_config.jobs/GenerateConfigPlans";
var redirectUrlTemplate = "/plugins/golden-config/config-plan/?job_result_id={jobData.result.id}";
var redirectUrlTemplate = "/plugins/golden-config/config-plan/?play_result_id={jobData.result.id}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var redirectUrlTemplate = "/plugins/golden-config/config-plan/?play_result_id={jobData.result.id}";
var redirectUrlTemplate = "/plugins/golden-config/config-plan/?plan_result_id={jobData.result.id}";

var changeControlUrlInput = document.getElementById("id_change_control_url");
var startJobButton = document.getElementById("startJob");
var form = document.querySelector("form");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,17 @@
<td><a href="{{ object.change_control_url }}">{{ object.change_control_url|placeholder }}</a></td>
</tr>
<tr>
<td>Job Result</td>
<td><a href="{{ object.job_result.get_absolute_url }}">{{ object.job_result.status|placeholder }}</a></td>
<td>Plan Result</td>
<td><a href="{{ object.plan_result.get_absolute_url }}">{{ object.plan_result.status|title }}</a></td>
</tr>
<tr>
<td>Deploy Result</td>
{% if object.deploy_result %}
<td><a href="{{ object.deploy_result.get_absolute_url }}">{{ object.deploy_result.status|title }}</a>
{% else %}
<td>{{ object.deploy_result|placeholder }}</td>
{% endif %}
</td>
</tr>
<tr>
<td>Status</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ <h3 class="modal-title">{{ modal_title }}</h3>
<td><div id="jobStatus" style="display:none;"></div></td>
</tr>
<tr>
<td>Job Results: </td>
<td>Plan Results: </td>
<td><div id="jobResults" style="display:none;"></div></td>
</tr>
<tr>
Expand Down
3 changes: 2 additions & 1 deletion nautobot_golden_config/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from nautobot.extras.models import DynamicGroup, GitRepository, GraphQLQuery, Status
from nautobot.utilities.testing import APITestCase, APIViewTestCases
from rest_framework import status

from nautobot_golden_config.choices import RemediationTypeChoice
from nautobot_golden_config.models import ConfigPlan, GoldenConfigSetting, RemediationSetting

Expand Down Expand Up @@ -376,7 +377,7 @@ def setUpTestData(cls):
change_control_id=f"Test Change Control ID {cont}",
change_control_url=f"https://{cont}.example.com/",
status=not_approved_status,
job_result_id=job_result_ids[cont - 1],
plan_result_id=job_result_ids[cont - 1],
)
plan.feature.add(features[cont - 1])
plan.validated_save()
Expand Down
17 changes: 9 additions & 8 deletions nautobot_golden_config/tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Unit tests for nautobot_golden_config models."""

from unittest import skip
from django.test import TestCase

from django.test import TestCase
from nautobot.dcim.models import Device, Platform
from nautobot.extras.models import Status, Tag
from nautobot.utilities.testing import FilterTestCases

from nautobot_golden_config import filters, models

from .conftest import create_feature_rule_json, create_device_data, create_feature_rule_cli, create_job_result
from .conftest import create_device_data, create_feature_rule_cli, create_feature_rule_json, create_job_result


class ConfigComplianceModelTestCase(TestCase):
Expand Down Expand Up @@ -335,7 +336,7 @@ def setUp(self):
config_set="intended test",
change_control_id="12345",
status=self.status2,
job_result_id=self.job_result1.id,
plan_result_id=self.job_result1.id,
)
self.config_plan1.tags.add(self.tag1)
self.config_plan1.feature.add(self.feature1)
Expand All @@ -347,7 +348,7 @@ def setUp(self):
config_set="missing test",
change_control_id="23456",
status=self.status1,
job_result_id=self.job_result1.id,
plan_result_id=self.job_result1.id,
)
self.config_plan2.tags.add(self.tag2)
self.config_plan2.feature.add(self.feature2)
Expand All @@ -359,7 +360,7 @@ def setUp(self):
config_set="remediation test",
change_control_id="34567",
status=self.status2,
job_result_id=self.job_result2.id,
plan_result_id=self.job_result2.id,
)
self.config_plan3.tags.add(self.tag2)
self.config_plan3.feature.set([self.feature1, self.feature3])
Expand All @@ -371,7 +372,7 @@ def setUp(self):
config_set="manual test",
change_control_id="45678",
status=self.status1,
job_result_id=self.job_result1.id,
plan_result_id=self.job_result1.id,
)
self.config_plan4.tags.add(self.tag1)
self.config_plan4.validated_save()
Expand Down Expand Up @@ -465,9 +466,9 @@ def test_filter_tag(self):

def test_job_result_id(self):
"""Test filtering by Job Result ID."""
params = {"job_result_id": [self.job_result1.pk]}
params = {"plan_result_id": [self.job_result1.pk]}
filterset = self.filterset(params, self.queryset)
self.assertEqual(filterset.qs.count(), 3)
self.assertQuerysetEqualAndNotEmpty(
filterset.qs, self.queryset.filter(job_result_id=self.job_result1.id).distinct()
filterset.qs, self.queryset.filter(plan_result_id=self.job_result1.id).distinct()
)
Loading