-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated template extensions to align with standard Nautobot UI views. (…
- Loading branch information
1 parent
eb4fe07
commit 4c9e46a
Showing
10 changed files
with
233 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Updated template extensions to align with standard Nautobot UI views. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Added management command `generate_app_test_data` to generate sample data for development environments. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
nautobot_device_lifecycle_mgmt/management/commands/generate_dlm_test_data.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
"""Generate test data for the Device Lifecycle Management app.""" | ||
|
||
import random | ||
|
||
from django.core.management import call_command | ||
from django.core.management.base import BaseCommand | ||
from django.db import DEFAULT_DB_ALIAS | ||
from nautobot.core.factory import get_random_instances | ||
from nautobot.dcim.models import Device, DeviceType, InventoryItem, Platform | ||
|
||
from nautobot_device_lifecycle_mgmt.choices import CVESeverityChoices | ||
from nautobot_device_lifecycle_mgmt.models import ( | ||
CVELCM, | ||
ContactLCM, | ||
ContractLCM, | ||
DeviceSoftwareValidationResult, | ||
HardwareLCM, | ||
InventoryItemSoftwareValidationResult, | ||
ProviderLCM, | ||
SoftwareImageLCM, | ||
SoftwareLCM, | ||
ValidatedSoftwareLCM, | ||
VulnerabilityLCM, | ||
) | ||
|
||
|
||
class Command(BaseCommand): | ||
"""Populate the database with various data as a baseline for testing (automated or manual).""" | ||
|
||
help = __doc__ | ||
|
||
def add_arguments(self, parser): # noqa: D102 | ||
parser.add_argument( | ||
"--database", | ||
default=DEFAULT_DB_ALIAS, | ||
help='The database to generate the test data in. Defaults to the "default" database.', | ||
) | ||
|
||
def _generate_static_data(self, db): | ||
devices = get_random_instances(Device.objects.using(db), minimum=2, maximum=4) | ||
device_types = get_random_instances(DeviceType.objects.using(db), minimum=2, maximum=4) | ||
inventory_items = get_random_instances(InventoryItem.objects.using(db), minimum=2, maximum=4) | ||
platforms = get_random_instances(Platform.objects.using(db), minimum=2, maximum=4) | ||
|
||
# create HardwareLCM | ||
for device_type in device_types: | ||
HardwareLCM.objects.using(db).create(device_type=device_type, end_of_sale="2022-03-14") | ||
for inventory_item in inventory_items: | ||
HardwareLCM.objects.using(db).create(inventory_item=inventory_item, end_of_support="2020-05-04") | ||
|
||
# create SoftwareLCM | ||
for platform in platforms: | ||
SoftwareLCM.objects.using(db).create( | ||
device_platform=platform, | ||
version=f"Test SoftwareLCM for {platform.name}", | ||
) | ||
|
||
# create SoftwareImageLCM | ||
for software in SoftwareLCM.objects.using(db).all(): | ||
SoftwareImageLCM.objects.using(db).create( | ||
software=software, | ||
image_file_name=f"{software.device_platform.name}_vxyz.bin", | ||
) | ||
|
||
# create ValidatedSoftwareLCM | ||
for software in SoftwareLCM.objects.using(db).all(): | ||
ValidatedSoftwareLCM.objects.using(db).create( | ||
software=software, | ||
start="2020-01-01", | ||
end="2020-12-31", | ||
) | ||
|
||
# create DeviceSoftwareValidationResult | ||
software_choices = list(SoftwareLCM.objects.using(db).all()) | ||
for device in devices: | ||
DeviceSoftwareValidationResult.objects.using(db).create( | ||
device=device, | ||
software=random.choice(software_choices), # noqa: S311 | ||
) | ||
|
||
# create InventoryItemSoftwareValidationResult | ||
for inventory_item in inventory_items: | ||
InventoryItemSoftwareValidationResult.objects.using(db).create( | ||
inventory_item=inventory_item, | ||
software=random.choice(software_choices), # noqa: S311 | ||
) | ||
|
||
# create ProviderLCM | ||
for i in range(1, 9): | ||
ProviderLCM.objects.using(db).create( | ||
name=f"Test Provider {i}", | ||
description=f"Description for Provider {i}", | ||
) | ||
|
||
# create ContractLCM | ||
for provider in ProviderLCM.objects.using(db).all(): | ||
ContractLCM.objects.using(db).create( | ||
provider=provider, | ||
name=f"Test Contract for {provider.name}", | ||
) | ||
|
||
# create ContactLCM | ||
for contract in ContractLCM.objects.using(db).all(): | ||
ContactLCM.objects.using(db).create( | ||
contract=contract, | ||
name=f"Test Contact for {contract.name}", | ||
) | ||
|
||
# create CVELCM | ||
for i in range(1, 5): | ||
cve = CVELCM.objects.using(db).create( | ||
name=f"Test CVELCM {i}", | ||
published_date="2020-01-01", | ||
link="http://cve.example.org/{i}/details/", | ||
severity=random.choice(CVESeverityChoices.values()), # noqa: S311 | ||
) | ||
cve.affected_softwares.set(get_random_instances(SoftwareLCM, minimum=1)) | ||
|
||
# create VulnerabilityLCM | ||
VulnerabilityLCM.objects.using(db).create(cve=CVELCM.objects.using(db).get(name="Test CVELCM 1")) | ||
VulnerabilityLCM.objects.using(db).create(software=SoftwareLCM.objects.using(db).first()) | ||
VulnerabilityLCM.objects.using(db).create(device=Device.objects.using(db).first()) | ||
VulnerabilityLCM.objects.using(db).create(inventory_item=InventoryItem.objects.using(db).first()) | ||
|
||
def handle(self, *args, **options): | ||
"""Entry point to the management command.""" | ||
self._generate_static_data(db=options["database"]) | ||
|
||
self.stdout.write(self.style.SUCCESS(f"Database {options['database']} populated with app data successfully!")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 64 additions & 100 deletions
164
...bot_device_lifecycle_mgmt/templates/nautobot_device_lifecycle_mgmt/inc/device_notice.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,72 @@ | ||
{% load helpers %} | ||
{% if perms.nautobot_device_lifecycle_mgmt.view_hardwarelcm and hw_notices %} | ||
<style type="text/css"> | ||
.panel-heading .accordion-toggle:after { | ||
/* symbol for "opening" panels */ | ||
font-family: 'Glyphicons Halflings'; /* essential for enabling glyphicon */ | ||
content: "\e114"; /* adjust as needed, taken from bootstrap.css */ | ||
float: right; /* adjust as needed */ | ||
color: grey; /* adjust as needed */ | ||
} | ||
.panel-heading .accordion-toggle.collapsed:after { | ||
/* symbol for "collapsed" panels */ | ||
content: "\e080"; /* adjust as needed, taken from bootstrap.css */ | ||
} | ||
</style> | ||
|
||
<div class="row"> | ||
<div class="col-md-12"> | ||
<!-- Nav tabs to support both hardware and software notices. --> | ||
<ul class="nav nav-tabs" role="tablist"> | ||
{% if hw_notices %} | ||
<li role="presentation" class="active"> | ||
<a href="#hardware" aria-controls="hardware" role="tab" data-toggle="tab"> | ||
Hardware Lifecycle Notices <span class="badge badge-pill badge-primary">{{ hw_notices.count }}</span> | ||
</a> | ||
|
||
</li> | ||
{% endif %} | ||
{% if sw_notices %} | ||
<li role="presentation"><a href="#software" aria-controls="software" role="tab" data-toggle="tab">Software Lifecycle Notices</a></li> | ||
{% endif %} | ||
</ul> | ||
|
||
<div class="tab-content"> | ||
<style> | ||
.accordion-toggle { | ||
font-size: 14px; | ||
font-weight: 700; | ||
} | ||
</style> | ||
|
||
<!-- Defines all hardware notice logic within this tab-panel. --> | ||
<div role="tabpanel" class="tab-pane active" id="hardware"> | ||
<div class="panel-group" id="hwAccordion" role="tablist" aria-multiselectable="true"> | ||
{% for notice in hw_notices %} | ||
{% if forloop.counter < 6 %} | ||
<div class="panel panel-{% if notice.expired %}danger{% else %}warning{% endif %}"> | ||
<div class="panel-heading" role="tab" id="heading{{ forloop.counter }}"> | ||
<span role="button" | ||
class="accordion-toggle collapsed" | ||
data-toggle="collapse" | ||
data-parent="#hwAccordion" | ||
href="#collapse{{ forloop.counter }}" | ||
aria-expanded="false" | ||
aria-controls="collapse{{ forloop.counter }}"> | ||
{{ notice }} | ||
</span> | ||
</div> | ||
<div id="collapse{{ forloop.counter }}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{ forloop.counter }}"> | ||
<div class="list-group"> | ||
<table class="table"> | ||
<tr> | ||
<td>End of Sale</td> | ||
<td>{{ notice.end_of_sale }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Support</td> | ||
<td>{{ notice.end_of_support }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Software Releases</td> | ||
<td>{{ notice.end_of_sw_releases }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Security Patches</td> | ||
<td>{{ notice.end_of_security_patches }}</td> | ||
</tr> | ||
<tr> | ||
<td>Documentation URL</td> | ||
<td> | ||
{% if notice.documentation_url %}<a href="{{ notice.documentation_url }}">{{ notice.documentation_url }}</a>{% else %}—{% endif %} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Comments</td> | ||
<td> | ||
{% if notice.comments %}<pre>{{ notice.comments }}</pre>{% else %}—{% endif %} | ||
</td> | ||
</tr> | ||
</table> | ||
</div> | ||
</div> | ||
</div> | ||
{% elif forloop.counter == 6 %} | ||
<div class="panel-footer text-right noprint"> | ||
<a href="{% url 'plugins:nautobot_device_lifecycle_mgmt:hardwarelcm_list' %}?q={% for inv in object.inventoryitems.all %}&inventory_item={{ inv.part_id }}{% endfor %}" target="_blank" class="btn btn-primary btn-xs"> | ||
<span class="mdi mdi-open-in-new" aria-hidden="true"></span> See More Notices | ||
</a> | ||
</div> | ||
{% endif %} | ||
{% endfor %} | ||
<div class="panel panel-default"> | ||
<div class="panel-heading"> | ||
<strong>Hardware Lifecycle Notices {% badge hw_notices.count show_empty=True %}</strong> | ||
</div> | ||
</div> | ||
|
||
<!-- Defines all software notice logic within this tab-panel. --> | ||
<div role="tabpanel" class="tab-pane" id="software"> | ||
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> | ||
|
||
<table id="accordion" class="table table-hover panel-body attr-table"> | ||
{% for notice in hw_notices|slice:":5" %} | ||
<tbody> | ||
<tr> | ||
<th colspan="2"> | ||
<button type="button" class="btn-link accordion-toggle mdi mdi-chevron-right" | ||
name="hardware-notices-accordion-{{ forloop.counter }}" data-toggle="collapse" | ||
data-target=".collapseme-hardware-notices-accordion-{{ forloop.counter }}"> | ||
{{ notice }} | ||
</button> | ||
{% if notice.expired %} | ||
<span class="label label-danger pull-right">Expired</span> | ||
{% endif %} | ||
</th> | ||
</tr> | ||
</tbody> | ||
<tbody class="collapse collapseme-hardware-notices-accordion-{{ forloop.counter }}"> | ||
<tr> | ||
<td>End of Sale</td> | ||
<td>{{ notice.end_of_sale|placeholder }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Support</td> | ||
<td>{{ notice.end_of_support|placeholder }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Software Releases</td> | ||
<td>{{ notice.end_of_sw_releases|placeholder }}</td> | ||
</tr> | ||
<tr> | ||
<td>End of Security Patches</td> | ||
<td>{{ notice.end_of_security_patches|placeholder }}</td> | ||
</tr> | ||
<tr> | ||
<td>Documentation URL</td> | ||
<td> | ||
{% if notice.documentation_url %}<a href="{{ notice.documentation_url }}">{{ notice.documentation_url }}</a>{% else %}{{ None|placeholder }}{% endif %} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Comments</td> | ||
<td> | ||
{% if notice.comments %}<pre>{{ notice.comments }}</pre>{% else %}{{ None|placeholder }}{% endif %} | ||
</td> | ||
</tr> | ||
</tbody> | ||
{% endfor %} | ||
</table> | ||
{% if hw_notices|length > 5 %} | ||
<div class="panel-footer text-right noprint"> | ||
<a href="{% url 'plugins:nautobot_device_lifecycle_mgmt:hardwarelcm_list' %}?q={% for inv in object.inventory_items.all %}{% if inv.part_id %}&inventory_item={{ inv.part_id|urlencode }}{% endif %}{% endfor %}" target="_blank" class="btn btn-primary btn-xs"> | ||
<span class="mdi mdi-open-in-new" aria-hidden="true"></span> | ||
See More Notices | ||
</a> | ||
</div> | ||
{% endif %} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
{% endif %} |
Oops, something went wrong.