mirror of
https://github.com/netbox-community/Device-Type-Library-Import.git
synced 2025-08-10 14:17:33 +02:00
Beta Release Merge (#87)
* Delete gitcmd.py * Delete nb-dt-import.py * Add files via upload * Logging cleanup (#78) * Removed multiple imports of settings.py * stating to abstract the netbox api calls to their own class * Abstracted away determine features from main script, implemented as part of class initialization * added helper functions to get repos relative & absolute path * renaming gitcmd to repo * starting to abstract away the get_files * fixed issue where spaces and commas in vendor list with/without spaces breaks matching * Added prelim fix for slugs if same issue vendors arg was facing exists. untested * Finished abstracting the get_files function. Reduced fors and ifs to be cleaner and more efficent * abstracted getFiles to repo class. Fixed slug issue not matching because of new slug format. added non-halting log function and renamed exception handler to log handler. * utilized new logging class throughout script to reduce excess logging * Abstracted and optimized create manufacturers * Abstracted the create interfaces for devices to the netbox api class * Fixed regression where check manufactuerers did not have the latest list * Fixed regression caused by externally calling script. Discovered from https://github.com/netbox-community/Device-Type-Library-Import/pull/76 * abstracted all device interfaces to the devicetype class. optimized function calls to reduce duplicate code and reduce extra log calls * Ran against all devices and passed with flying colors * formatting settings.py * formatting repo.py * formatting main file * formatting log_handler.py * added back executable on file (#79) * Add more info to failed device_type creations (#81) --------- Co-authored-by: Philipp Rintz <13933258+p-rintz@users.noreply.github.com>
This commit is contained in:
103
repo.py
Normal file
103
repo.py
Normal file
@ -0,0 +1,103 @@
|
||||
import os
|
||||
from glob import glob
|
||||
from re import sub as re_sub
|
||||
from git import Repo, exc
|
||||
import yaml
|
||||
|
||||
|
||||
class DTLRepo:
|
||||
def __new__(cls, *args, **kwargs):
|
||||
return super().__new__(cls)
|
||||
|
||||
def __init__(self, args, repo_path, exception_handler):
|
||||
self.handle = exception_handler
|
||||
self.yaml_extensions = ['yaml', 'yml']
|
||||
self.url = args.url
|
||||
self.repo_path = repo_path
|
||||
self.branch = args.branch
|
||||
self.repo = None
|
||||
self.cwd = os.getcwd()
|
||||
|
||||
if os.path.isdir(self.repo_path):
|
||||
self.pull_repo()
|
||||
else:
|
||||
self.clone_repo()
|
||||
|
||||
def get_relative_path(self):
|
||||
return self.repo_path
|
||||
|
||||
def get_absolute_path(self):
|
||||
return os.path.join(self.cwd, self.repo_path)
|
||||
|
||||
def get_devices_path(self):
|
||||
return os.path.join(self.get_absolute_path(), 'device-types')
|
||||
|
||||
def get_modules_path(self):
|
||||
return os.path.join(self.get_absolute_path(), 'module-types')
|
||||
|
||||
def slug_format(self, name):
|
||||
return re_sub('\W+', '-', name.lower())
|
||||
|
||||
def pull_repo(self):
|
||||
try:
|
||||
self.handle.log("Package devicetype-library is already installed, "
|
||||
+ f"updating {self.get_absolute_path()}")
|
||||
self.repo = Repo(self.repo_path)
|
||||
if not self.repo.remotes.origin.url.endswith('.git'):
|
||||
self.handle.exception("GitInvalidRepositoryError", self.repo.remotes.origin.url,
|
||||
f"Origin URL {self.repo.remotes.origin.url} does not end with .git")
|
||||
self.repo.remotes.origin.pull()
|
||||
self.repo.git.checkout(self.branch)
|
||||
self.handle.verbose_log(
|
||||
f"Pulled Repo {self.repo.remotes.origin.url}")
|
||||
except exc.GitCommandError as git_error:
|
||||
self.handle.exception(
|
||||
"GitCommandError", self.repo.remotes.origin.url, git_error)
|
||||
except Exception as git_error:
|
||||
self.handle.exception(
|
||||
"Exception", 'Git Repository Error', git_error)
|
||||
|
||||
def clone_repo(self):
|
||||
try:
|
||||
self.repo = Repo.clone_from(
|
||||
self.url, self.get_absolute_path(), branch=self.branch)
|
||||
self.handle.log(
|
||||
f"Package Installed {self.repo.remotes.origin.url}")
|
||||
except exc.GitCommandError as git_error:
|
||||
self.handle.exception("GitCommandError", self.url, git_error)
|
||||
except Exception as git_error:
|
||||
self.handle.exception(
|
||||
"Exception", 'Git Repository Error', git_error)
|
||||
|
||||
def get_devices(self, base_path, vendors: list = None):
|
||||
files = []
|
||||
discovered_vendors = []
|
||||
vendor_dirs = os.listdir(base_path)
|
||||
|
||||
for folder in [vendor for vendor in vendor_dirs if not vendors or vendor.casefold() in vendors]:
|
||||
if folder.casefold() != "testing":
|
||||
discovered_vendors.append({'name': folder,
|
||||
'slug': self.slug_format(folder)})
|
||||
for extension in self.yaml_extensions:
|
||||
files.extend(glob(base_path + folder + f'/*.{extension}'))
|
||||
return files, discovered_vendors
|
||||
|
||||
def parse_files(self, files: list, slugs: list = None):
|
||||
deviceTypes = []
|
||||
for file in files:
|
||||
with open(file, 'r') as stream:
|
||||
try:
|
||||
data = yaml.safe_load(stream)
|
||||
except yaml.YAMLError as excep:
|
||||
self.handle.verbose_log(excep)
|
||||
continue
|
||||
manufacturer = data['manufacturer']
|
||||
data['manufacturer'] = {
|
||||
'name': manufacturer, 'slug': self.slug_format(manufacturer)}
|
||||
|
||||
if slugs and True not in [True if s.casefold() in data['slug'].casefold() else False for s in slugs]:
|
||||
self.handle.verbose_log(f"Skipping {data['model']}")
|
||||
continue
|
||||
|
||||
deviceTypes.append(data)
|
||||
return deviceTypes
|
Reference in New Issue
Block a user