From 2fc79af4c72fc5e936b897a610c522fc8dd4635f Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 22 Mar 2023 09:20:44 -0400 Subject: [PATCH] #11558: Cleanup & docs --- docs/features/synchronized-data.md | 23 ++++++++++++++++++++ mkdocs.yml | 1 + netbox/netbox/api/features.py | 2 +- netbox/netbox/models/features.py | 17 ++++++++++++--- netbox/netbox/views/generic/feature_views.py | 4 ++-- 5 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 docs/features/synchronized-data.md diff --git a/docs/features/synchronized-data.md b/docs/features/synchronized-data.md new file mode 100644 index 000000000..3fb48425e --- /dev/null +++ b/docs/features/synchronized-data.md @@ -0,0 +1,23 @@ +# Synchronized Data + +!!! info "This feature was introduced in NetBox v3.5." + +Several models in NetBox support the automatic synchronization of local data from a designated remote source. For example, [configuration templates](./configuration-rendering.md) defined in NetBox can source their content from text files stored in a remote git repository. This accomplished using the core [data source](../models/core/datasource.md) and [data file](../models/core/datafile.md) models. + +To enable remote data synchronization, the NetBox administrator first designates one or more remote data sources. NetBox currently supports the following source types: + +* Git repository +* Amazon S3 bucket (or compatible product) +* Local disk path + +(Local disk paths are considered "remote" in this context as they exist outside NetBox's database. These paths could also be mapped to external network shares.) + +Each type of remote source has its own configuration parameters. For instance, a git source will ask the user to specify a branch and authentication credentials. Once the source has been created, a synchronization job is run to automatically replicate remote files in the local database. + +The following NetBox models can be associated with replicated data files: + +* Config contexts +* Config templates +* Export templates + +Once a data has been designated for a local instance, its data will be replaced with the content of the replicated file. When the replicated file is updated in the future (via synchronization jobs), the local instance will be flagged as having out-of-date data. A user can then synchronize these objects individually or in bulk to effect the update. This two-stgae process ensures that automated synchronization tasks do not immediately affect production data. diff --git a/mkdocs.yml b/mkdocs.yml index 2c24d2e00..b5ce9bf00 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,6 +75,7 @@ nav: - Search: 'features/search.md' - Context Data: 'features/context-data.md' - Configuration Rendering: 'features/configuration-rendering.md' + - Synchronized Data: 'features/synchronized-data.md' - Change Logging: 'features/change-logging.md' - Journaling: 'features/journaling.md' - Background Jobs: 'features/background-jobs.md' diff --git a/netbox/netbox/api/features.py b/netbox/netbox/api/features.py index db018ca12..3c2a096c6 100644 --- a/netbox/netbox/api/features.py +++ b/netbox/netbox/api/features.py @@ -23,7 +23,7 @@ class SyncedDataMixin: obj = get_object_or_404(self.queryset, pk=pk) if obj.data_file: - obj.sync_data() + obj.sync() obj.save() serializer = self.serializer_class(obj, context={'request': request}) diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 2144d1c0f..682540f34 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -336,7 +336,7 @@ class WebhooksMixin(models.Model): class SyncedDataMixin(models.Model): """ - Enables population of local data from a DataFile object, synchronized from a remote DatSource. + Enables population of local data from a DataFile object, synchronized from a remote DataSource. """ data_source = models.ForeignKey( to='core.DataSource', @@ -377,8 +377,7 @@ class SyncedDataMixin(models.Model): if self.data_file: self.data_source = self.data_file.source self.data_path = self.data_file.path - self.sync_data() - self.data_synced = timezone.now() + self.sync() else: self.data_source = None self.data_path = '' @@ -399,7 +398,19 @@ class SyncedDataMixin(models.Model): except DataFile.DoesNotExist: pass + def sync(self): + """ + Synchronize the object from it's assigned DataFile (if any). This wraps sync_data() and updates + the synced_data timestamp. + """ + self.sync_data() + self.data_synced = timezone.now() + def sync_data(self): + """ + Inheriting models must override this method with specific logic to copy data from the assigned DataFile + to the local instance. This method should *NOT* call save() on the instance. + """ raise NotImplementedError(f"{self.__class__} must implement a sync_data() method.") diff --git a/netbox/netbox/views/generic/feature_views.py b/netbox/netbox/views/generic/feature_views.py index 6e310c97a..8181b6d20 100644 --- a/netbox/netbox/views/generic/feature_views.py +++ b/netbox/netbox/views/generic/feature_views.py @@ -149,7 +149,7 @@ class ObjectSyncDataView(View): messages.error(request, f"Unable to synchronize data: No data file set.") return redirect(obj.get_absolute_url()) - obj.sync_data() + obj.sync() obj.save() messages.success(request, f"Synchronized data for {model._meta.verbose_name} {obj}.") @@ -171,7 +171,7 @@ class BulkSyncDataView(GetReturnURLMixin, BaseMultiObjectView): with transaction.atomic(): for obj in selected_objects: - obj.sync_data() + obj.sync() obj.save() model_name = self.queryset.model._meta.verbose_name_plural