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

Jmcgill/2.x jobs rebase #595

Merged
merged 3 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions docs/admin/compatibility_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ While that last supported version will not be strictly enforced via the `max_ver
| 1.3.X | 1.4.0 | 1.5.2 [Official] |
| 1.4.X | 1.5.3 | 1.5.99 [Official] |
| 1.5.X | 1.6.1 | 1.6.99 [Official] |
| 2.0.x | 2.0.0 | TBD |
113 changes: 24 additions & 89 deletions nautobot_golden_config/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from datetime import datetime

from nautobot.core.celery import register_jobs
from nautobot.dcim.models import Device, DeviceType, Manufacturer, Platform, Rack, RackGroup, Location
from nautobot.extras.datasources.git import ensure_git_repository
from nautobot.extras.jobs import (
Expand Down Expand Up @@ -58,7 +59,7 @@ def get_refreshed_repos(job_obj, repo_type, data=None):
repositories = []
for repository_record in repository_records:
repo = GitRepository.objects.get(id=repository_record)
ensure_git_repository(repo, job_obj.job_result)
ensure_git_repository(repo, job_obj.logger)
git_repo = GitRepo(repo)
repositories.append(git_repo)

Expand Down Expand Up @@ -95,31 +96,15 @@ class FormEntry: # pylint disable=too-few-public-method
class ComplianceJob(Job, FormEntry):
"""Job to to run the compliance engine."""

tenant_group = FormEntry.tenant_group
tenant = FormEntry.tenant
location = FormEntry.location
rack_group = FormEntry.rack_group
rack = FormEntry.rack
role = FormEntry.role
manufacturer = FormEntry.manufacturer
platform = FormEntry.platform
device_type = FormEntry.device_type
device = FormEntry.device
tag = FormEntry.tag
status = FormEntry.status
debug = FormEntry.debug

class Meta:
"""Meta object boilerplate for compliance."""

name = "Perform Configuration Compliance"
description = "Run configuration compliance on your network infrastructure."

def run(self, **data): # pylint: disable=too-many-branches
def run(self, *args, **data):
"""Run config compliance report script."""
# pylint: disable=unused-argument
self.logger.debug("Starting compliance job.")

self.logger.debug("Refreshing intended configuration git repository.")
get_refreshed_repos(job_obj=self, repo_type="intended_repository", data=data)
self.logger.debug("Refreshing backup configuration git repository.")
Expand All @@ -132,32 +117,16 @@ def run(self, **data): # pylint: disable=too-many-branches
class IntendedJob(Job, FormEntry):
"""Job to to run generation of intended configurations."""

tenant_group = FormEntry.tenant_group
tenant = FormEntry.tenant
location = FormEntry.location
rack_group = FormEntry.rack_group
rack = FormEntry.rack
role = FormEntry.role
manufacturer = FormEntry.manufacturer
platform = FormEntry.platform
device_type = FormEntry.device_type
device = FormEntry.device
tag = FormEntry.tag
status = FormEntry.status
debug = FormEntry.debug

class Meta:
"""Meta object boilerplate for intended."""

name = "Generate Intended Configurations"
description = "Generate the configuration for your intended state."

def run(self, **data):
def run(self, *args, **data):
"""Run config generation script."""
self.logger.debug("Starting intended job.")

now = datetime.now()

self.logger.debug("Pull Jinja template repos.")
get_refreshed_repos(job_obj=self, repo_type="jinja_repository", data=data)

Expand All @@ -170,35 +139,21 @@ def run(self, **data):

# Commit / Push each repo after job is completed.
for intended_repo in intended_repos:
self.logger.debug(f"Push new intended configs to repo {intended_repo.url}.")
self.logger.debug("Push new intended configs to repo %s.", intended_repo.url)
intended_repo.commit_with_added(f"INTENDED CONFIG CREATION JOB - {now}")
intended_repo.push()


class BackupJob(Job, FormEntry):
"""Job to to run the backup job."""

tenant_group = FormEntry.tenant_group
tenant = FormEntry.tenant
location = FormEntry.location
rack_group = FormEntry.rack_group
rack = FormEntry.rack
role = FormEntry.role
manufacturer = FormEntry.manufacturer
platform = FormEntry.platform
device_type = FormEntry.device_type
device = FormEntry.device
tag = FormEntry.tag
status = FormEntry.status
debug = FormEntry.debug

class Meta:
"""Meta object boilerplate for backup configurations."""

name = "Backup Configurations"
description = "Backup the configurations of your network devices."

def run(self, **data):
def run(self, *args, **data):
"""Run config backup process."""
self.logger.debug("Starting backup job.")
now = datetime.now()
Expand All @@ -207,14 +162,13 @@ def run(self, **data):
# Instantiate a GitRepo object for each GitRepository in GoldenConfigSettings.
backup_repos = get_refreshed_repos(job_obj=self, repo_type="backup_repository", data=data)

self.logger.debug(f"Starting backup jobs to the following repos: {backup_repos}")

self.logger.debug("Starting backup jobs to the following repos: %s", backup_repos)
self.logger.debug("Starting config backup nornir play.")
config_backup(self, data)

# Commit / Push each repo after job is completed.
for backup_repo in backup_repos:
self.logger.debug(f"Pushing Backup config repo {backup_repo.url}.")
self.logger.debug("Pushing Backup config repo %s.", backup_repo.url)
backup_repo.commit_with_added(f"BACKUP JOB {now}")
backup_repo.push()

Expand All @@ -231,47 +185,33 @@ class Meta:
name = "Execute All Golden Configuration Jobs - Single Device"
description = "Process to run all Golden Configuration jobs configured."

def run(self, **data):
def run(self, *args, **data):
"""Run all jobs."""
if ENABLE_INTENDED:
IntendedJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
IntendedJob().run.__func__(self, data, True)
if ENABLE_BACKUP:
BackupJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
BackupJob().run.__func__(self, data, True)
if ENABLE_COMPLIANCE:
ComplianceJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
ComplianceJob().run.__func__(self, data, True)


class AllDevicesGoldenConfig(Job):
"""Job to to run all three jobs against multiple devices."""

tenant_group = FormEntry.tenant_group
tenant = FormEntry.tenant
location = FormEntry.location
rack_group = FormEntry.rack_group
rack = FormEntry.rack
role = FormEntry.role
manufacturer = FormEntry.manufacturer
platform = FormEntry.platform
device_type = FormEntry.device_type
device = FormEntry.device
tag = FormEntry.tag
status = FormEntry.status
debug = FormEntry.debug

class Meta:
"""Meta object boilerplate for all jobs to run against multiple devices."""

name = "Execute All Golden Configuration Jobs - Multiple Device"
description = "Process to run all Golden Configuration jobs configured against multiple devices."

def run(self, **data):
def run(self, *args, **data):
"""Run all jobs."""
if ENABLE_INTENDED:
IntendedJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
IntendedJob().run.__func__(self, data, True)
if ENABLE_BACKUP:
BackupJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
BackupJob().run.__func__(self, data, True)
if ENABLE_COMPLIANCE:
ComplianceJob().run.__func__(self, data, True) # pylint: disable=too-many-function-args
ComplianceJob().run.__func__(self, data, True)


class GenerateConfigPlans(Job, FormEntry):
Expand Down Expand Up @@ -444,19 +384,14 @@ def receive_job_button(self, obj):


# Conditionally allow jobs based on whether or not turned on.
jobs = []
if ENABLE_BACKUP:
jobs.append(BackupJob)
register_jobs(BackupJob)
if ENABLE_INTENDED:
jobs.append(IntendedJob)
register_jobs(IntendedJob)
if ENABLE_COMPLIANCE:
jobs.append(ComplianceJob)
jobs.extend(
[
AllGoldenConfig,
AllDevicesGoldenConfig,
GenerateConfigPlans,
DeployConfigPlans,
DeployConfigPlanJobButtonReceiver,
]
)
register_jobs(ComplianceJob)
register_jobs(GenerateConfigPlans)
register_jobs(DeployConfigPlans)
register_jobs(DeployConfigPlanJobButtonReceiver)
register_jobs(AllGoldenConfig)
register_jobs(AllDevicesGoldenConfig)
7 changes: 4 additions & 3 deletions nautobot_golden_config/nornir_plays/config_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
InventoryPluginRegister.register("nautobot-inventory", NautobotORMInventory)


@close_threaded_db_connections
@close_threaded_db_connections # TODO: Is this still needed?
def run_backup( # pylint: disable=too-many-arguments
task: Task, logger, device_to_settings_map, remove_regex_dict, replace_regex_dict
) -> Result:
Expand Down Expand Up @@ -92,10 +92,11 @@ def run_backup( # pylint: disable=too-many-arguments
return Result(host=task.host, result=running_config)


def config_backup(job_result, data):
def config_backup(job_class_instance, data):
"""Nornir play to backup configurations."""
now = datetime.now()
logger = NornirLogger(__name__, job_result, data.get("debug"))
# TODO: nornir-nautobot needs to fix log_* methods for Nautobot Job classes in 2.x
logger = NornirLogger(__name__, job_class_instance, data.get("debug"))

qs = get_job_filter(data)
logger.log_debug("Compiling device data for backup.")
Expand Down
5 changes: 3 additions & 2 deletions nautobot_golden_config/nornir_plays/config_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,12 @@ def run_compliance( # pylint: disable=too-many-arguments,too-many-locals
return Result(host=task.host)


def config_compliance(job_result, data):
def config_compliance(job_class_instance, data):
"""Nornir play to generate configurations."""
now = datetime.now()
rules = get_rules()
logger = NornirLogger(__name__, job_result, data.get("debug"))
# TODO: nornir-nautobot needs to fix log_* methods for Nautobot Job classes in 2.x
logger = NornirLogger(__name__, job_class_instance, data.get("debug"))

qs = get_job_filter(data)
logger.log_debug("Compiling device data for compliance job.")
Expand Down
15 changes: 8 additions & 7 deletions nautobot_golden_config/nornir_plays/config_intended.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

@close_threaded_db_connections
def run_template( # pylint: disable=too-many-arguments
task: Task, logger, device_to_settings_map, nautobot_job
task: Task, logger, device_to_settings_map, job_class_instance
) -> Result:
"""Render Jinja Template.

Expand All @@ -53,7 +53,7 @@ def run_template( # pylint: disable=too-many-arguments
task (Task): Nornir task individual object
logger (NornirLogger): Logger to log messages to.
global_settings (GoldenConfigSetting): The settings for GoldenConfigPlugin.
nautobot_job (Result): The the output from the Nautobot Job instance being run.
job_class_instance (Result): The the output from the Nautobot Job instance being run.

Returns:
result (Result): Result from Nornir task
Expand All @@ -72,7 +72,7 @@ def run_template( # pylint: disable=too-many-arguments
output_file_location = os.path.join(intended_directory, intended_path_template_obj)

jinja_template = render_jinja_template(obj, logger, settings.jinja_path_template)
status, device_data = graph_ql_query(nautobot_job.request, obj, settings.sot_agg_query.query)
status, device_data = graph_ql_query(job_class_instance.request, obj, settings.sot_agg_query.query)
if status != 200:
error_msg = f"E3012: The GraphQL query return a status of {str(status)} with error of {str(device_data)}"
logger.log_error(error_msg, extra={"object": obj})
Expand Down Expand Up @@ -102,19 +102,20 @@ def run_template( # pylint: disable=too-many-arguments
return Result(host=task.host, result=generated_config)


def config_intended(nautobot_job, data):
def config_intended(job_class_instance, data):
"""
Nornir play to generate configurations.

Args:
nautobot_job (Result): The Nautobot Job instance being run.
job_class_instance (Job): The Nautobot Job instance being run.
data (dict): Form data from Nautobot Job.

Returns:
None: Intended configuration files are written to filesystem.
"""
now = datetime.now()
logger = NornirLogger(__name__, nautobot_job, data.get("debug"))
# TODO: nornir-nautobot needs to fix log_* methods for Nautobot Job classes in 2.x
logger = NornirLogger(__name__, job_class_instance, data.get("debug"))

qs = get_job_filter(data)
logger.log_debug("Compiling device data for intended configuration.")
Expand Down Expand Up @@ -146,7 +147,7 @@ def config_intended(nautobot_job, data):
name="RENDER CONFIG",
logger=logger,
device_to_settings_map=device_to_settings_map,
nautobot_job=nautobot_job,
job_class_instance=job_class_instance,
)

except Exception as err:
Expand Down
Loading