release.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import datetime
  2. import os
  3. from dataclasses import asdict, dataclass, field
  4. from typing import Union
  5. import yaml
  6. from django.core.exceptions import ImproperlyConfigured
  7. from utilities.datetime import datetime_from_timestamp
  8. RELEASE_PATH = 'release.yaml'
  9. LOCAL_RELEASE_PATH = 'local/release.yaml'
  10. @dataclass
  11. class FeatureSet:
  12. """
  13. A map of all available NetBox features.
  14. """
  15. # Commercial support is provided by NetBox Labs
  16. commercial: bool = False
  17. # Live help center is enabled
  18. help_center: bool = False
  19. @dataclass
  20. class ReleaseInfo:
  21. version: str
  22. edition: str
  23. published: Union[datetime.date, None] = None
  24. designation: Union[str, None] = None
  25. build: Union[str, None] = None
  26. features: FeatureSet = field(default_factory=FeatureSet)
  27. @property
  28. def full_version(self):
  29. output = self.version
  30. if self.designation:
  31. output = f"{output}-{self.designation}"
  32. if self.build:
  33. output = f"{output}-{self.build}"
  34. return output
  35. @property
  36. def name(self):
  37. return f"NetBox {self.edition} v{self.full_version}"
  38. def asdict(self):
  39. return asdict(self)
  40. def load_release_data():
  41. """
  42. Load any locally-defined release attributes and return a ReleaseInfo instance.
  43. """
  44. base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  45. # Load canonical release attributes
  46. with open(os.path.join(base_path, RELEASE_PATH), 'r') as release_file:
  47. data = yaml.safe_load(release_file)
  48. # Overlay any local release date (if defined)
  49. try:
  50. with open(os.path.join(base_path, LOCAL_RELEASE_PATH), 'r') as release_file:
  51. local_data = yaml.safe_load(release_file)
  52. except FileNotFoundError:
  53. local_data = {}
  54. if local_data is not None:
  55. if type(local_data) is not dict:
  56. raise ImproperlyConfigured(
  57. f"{LOCAL_RELEASE_PATH}: Local release data must be defined as a dictionary."
  58. )
  59. data.update(local_data)
  60. # Convert the published date to a date object
  61. if 'published' in data:
  62. data['published'] = datetime_from_timestamp(data['published'])
  63. return ReleaseInfo(**data)