From 83c6149e499382690b88264486baf820f963e82f Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 10 Mar 2026 08:46:47 -0700 Subject: [PATCH] #21114 Allow specifying exclude directories for Data Sources --- docs/models/core/datasource.md | 15 +++++++++------ netbox/core/forms/model_forms.py | 2 +- netbox/core/models/data.py | 15 ++++++++------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/models/core/datasource.md b/docs/models/core/datasource.md index 64a087cb6..23d06f610 100644 --- a/docs/models/core/datasource.md +++ b/docs/models/core/datasource.md @@ -36,13 +36,16 @@ If false, synchronization will be disabled. ### Ignore Rules -A set of rules (one per line) identifying filenames to ignore during synchronization. Some examples are provided below. See Python's [`fnmatch()` documentation](https://docs.python.org/3/library/fnmatch.html) for a complete reference. +A set of rules (one per line) identifying files or paths to ignore during synchronization. Rules are matched against both the full relative path (e.g. `subdir/file.txt`) and the bare filename, so path-based patterns can be used to exclude entire directories. Some examples are provided below. See Python's [`fnmatch()` documentation](https://docs.python.org/3/library/fnmatch.html) for a complete reference. -| Rule | Description | -|----------------|------------------------------------------| -| `README` | Ignore any files named `README` | -| `*.txt` | Ignore any files with a `.txt` extension | -| `data???.json` | Ignore e.g. `data123.json` | +| Rule | Description | +|-----------------------|------------------------------------------------------| +| `README` | Ignore any files named `README` | +| `*.txt` | Ignore any files with a `.txt` extension | +| `data???.json` | Ignore e.g. `data123.json` | +| `subdir/*` | Ignore all files directly within `subdir/` | +| `subdir/*/*` | Ignore all files one level deep within `subdir/` | +| `*/dev/*` | Ignore files inside any directory named `dev/` | ### Sync Interval diff --git a/netbox/core/forms/model_forms.py b/netbox/core/forms/model_forms.py index 4f26d6024..bcfabe265 100644 --- a/netbox/core/forms/model_forms.py +++ b/netbox/core/forms/model_forms.py @@ -43,7 +43,7 @@ class DataSourceForm(PrimaryModelForm): attrs={ 'rows': 5, 'class': 'font-monospace', - 'placeholder': '.cache\n*.txt' + 'placeholder': '.cache\n*.txt\nsubdir/*' } ), } diff --git a/netbox/core/models/data.py b/netbox/core/models/data.py index 1047fbd14..5555c655e 100644 --- a/netbox/core/models/data.py +++ b/netbox/core/models/data.py @@ -69,7 +69,7 @@ class DataSource(JobsMixin, PrimaryModel): ignore_rules = models.TextField( verbose_name=_('ignore rules'), blank=True, - help_text=_("Patterns (one per line) matching files to ignore when syncing") + help_text=_("Patterns (one per line) matching files or paths to ignore when syncing") ) parameters = models.JSONField( verbose_name=_('parameters'), @@ -258,21 +258,22 @@ class DataSource(JobsMixin, PrimaryModel): if path.startswith('.'): continue for file_name in file_names: - if not self._ignore(file_name): - paths.add(os.path.join(path, file_name)) + file_path = os.path.join(path, file_name) + if not self._ignore(file_path): + paths.add(file_path) logger.debug(f"Found {len(paths)} files") return paths - def _ignore(self, filename): + def _ignore(self, file_path): """ Returns a boolean indicating whether the file should be ignored per the DataSource's configured - ignore rules. + ignore rules. file_path is the full relative path (e.g. "subdir/file.txt"). """ - if filename.startswith('.'): + if os.path.basename(file_path).startswith('.'): return True for rule in self.ignore_rules.splitlines(): - if fnmatchcase(filename, rule): + if fnmatchcase(file_path, rule) or fnmatchcase(os.path.basename(file_path), rule): return True return False