saltext-opnsense 0.1.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. saltext_opnsense-0.1.1.dev0/.github/workflows/ci.yml +50 -0
  2. saltext_opnsense-0.1.1.dev0/.github/workflows/publish.yml +41 -0
  3. saltext_opnsense-0.1.1.dev0/.gitignore +20 -0
  4. saltext_opnsense-0.1.1.dev0/.pre-commit-config.yaml +23 -0
  5. saltext_opnsense-0.1.1.dev0/CHANGELOG.md +9 -0
  6. saltext_opnsense-0.1.1.dev0/CONTRIBUTING.md +128 -0
  7. saltext_opnsense-0.1.1.dev0/LICENSE +21 -0
  8. saltext_opnsense-0.1.1.dev0/MANIFEST.in +10 -0
  9. saltext_opnsense-0.1.1.dev0/Makefile +92 -0
  10. saltext_opnsense-0.1.1.dev0/PKG-INFO +137 -0
  11. saltext_opnsense-0.1.1.dev0/README.md +104 -0
  12. saltext_opnsense-0.1.1.dev0/changelog/README.md +10 -0
  13. saltext_opnsense-0.1.1.dev0/docs/ARCHITECTURE.md +239 -0
  14. saltext_opnsense-0.1.1.dev0/docs/DEVELOPMENT.md +90 -0
  15. saltext_opnsense-0.1.1.dev0/docs/FIREWALL_SAFETY.md +201 -0
  16. saltext_opnsense-0.1.1.dev0/docs/MAINTENANCE.md +197 -0
  17. saltext_opnsense-0.1.1.dev0/docs/Makefile +12 -0
  18. saltext_opnsense-0.1.1.dev0/docs/USAGE.md +704 -0
  19. saltext_opnsense-0.1.1.dev0/docs/conf.py +23 -0
  20. saltext_opnsense-0.1.1.dev0/docs/index.rst +14 -0
  21. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/file-based-proxy.yaml +57 -0
  22. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/full_example.sls +358 -0
  23. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/full_example.sls.example +542 -0
  24. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/opnsense-router.sls +15 -0
  25. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/opnsense.sls +112 -0
  26. saltext_opnsense-0.1.1.dev0/docs/tutorials/pillars/top.sls.example +35 -0
  27. saltext_opnsense-0.1.1.dev0/docs/tutorials/proxy/opnsense-router +8 -0
  28. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/acme_certificates.sls +201 -0
  29. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/bind_records.sls +42 -0
  30. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/delightful_aliases.sls +85 -0
  31. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/free_modules_demo.sls +50 -0
  32. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/host_overrides.sls +21 -0
  33. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/kea_reservations.sls +104 -0
  34. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/metrics.sls +73 -0
  35. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/unbound_aliases.sls +48 -0
  36. saltext_opnsense-0.1.1.dev0/docs/tutorials/states/unbound_aliases_batch.sls +57 -0
  37. saltext_opnsense-0.1.1.dev0/noxfile.py +29 -0
  38. saltext_opnsense-0.1.1.dev0/pillar.example +97 -0
  39. saltext_opnsense-0.1.1.dev0/pyproject.toml +101 -0
  40. saltext_opnsense-0.1.1.dev0/setup.cfg +4 -0
  41. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/__init__.py +6 -0
  42. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/grains/opnsense.py +46 -0
  43. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/acmeclient.py +171 -0
  44. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/bind.py +229 -0
  45. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/dns.py +181 -0
  46. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/firewall.py +105 -0
  47. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/kea.py +206 -0
  48. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/opnsense.py +531 -0
  49. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/modules/unbound.py +308 -0
  50. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/proxy/opnsense.py +164 -0
  51. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/states/bind.py +460 -0
  52. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/states/dns.py +352 -0
  53. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/states/opnsense.py +1986 -0
  54. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/states/unbound.py +539 -0
  55. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/api_spec.py +158 -0
  56. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/common.py +99 -0
  57. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/controllers.json +4982 -0
  58. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/models.json +16010 -0
  59. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/models.py +239 -0
  60. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/utils/opnsense.py +658 -0
  61. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/version/__init__.py +10 -0
  62. saltext_opnsense-0.1.1.dev0/src/saltext/opnsense/version/_version.py +24 -0
  63. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/PKG-INFO +137 -0
  64. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/SOURCES.txt +92 -0
  65. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/dependency_links.txt +1 -0
  66. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/entry_points.txt +2 -0
  67. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/requires.txt +3 -0
  68. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/scm_file_list.json +88 -0
  69. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/scm_version.json +8 -0
  70. saltext_opnsense-0.1.1.dev0/src/saltext_opnsense.egg-info/top_level.txt +1 -0
  71. saltext_opnsense-0.1.1.dev0/tests/__init__.py +0 -0
  72. saltext_opnsense-0.1.1.dev0/tests/conftest.py +41 -0
  73. saltext_opnsense-0.1.1.dev0/tests/integration/README.md +42 -0
  74. saltext_opnsense-0.1.1.dev0/tests/integration/__init__.py +0 -0
  75. saltext_opnsense-0.1.1.dev0/tests/integration/test_live_opnsense.py +45 -0
  76. saltext_opnsense-0.1.1.dev0/tests/unit/modules/test_exec_helpers.py +165 -0
  77. saltext_opnsense-0.1.1.dev0/tests/unit/modules/test_exec_wrappers_generated.py +75 -0
  78. saltext_opnsense-0.1.1.dev0/tests/unit/modules/test_modules_opnsense.py +22 -0
  79. saltext_opnsense-0.1.1.dev0/tests/unit/proxy/test_proxy_opnsense.py +34 -0
  80. saltext_opnsense-0.1.1.dev0/tests/unit/states/test_state_helpers.py +239 -0
  81. saltext_opnsense-0.1.1.dev0/tests/unit/states/test_state_reconfigure.py +456 -0
  82. saltext_opnsense-0.1.1.dev0/tests/unit/states/test_state_wrappers_generated.py +54 -0
  83. saltext_opnsense-0.1.1.dev0/tests/unit/states/test_states_opnsense.py +279 -0
  84. saltext_opnsense-0.1.1.dev0/tests/unit/test_client.py +393 -0
  85. saltext_opnsense-0.1.1.dev0/tests/unit/test_free_modules_import.py +82 -0
  86. saltext_opnsense-0.1.1.dev0/tools/README.md +40 -0
  87. saltext_opnsense-0.1.1.dev0/tools/generate_all.py +275 -0
  88. saltext_opnsense-0.1.1.dev0/tools/generate_models.py +376 -0
  89. saltext_opnsense-0.1.1.dev0/tools/generate_pillar_example.py +100 -0
  90. saltext_opnsense-0.1.1.dev0/tools/generate_spec.py +177 -0
  91. saltext_opnsense-0.1.1.dev0/tools/generate_wrappers.py +963 -0
  92. saltext_opnsense-0.1.1.dev0/tools/sync_extmods.py +158 -0
  93. saltext_opnsense-0.1.1.dev0/tools/test_live.py +67 -0
  94. saltext_opnsense-0.1.1.dev0/tools/verify_import.py +76 -0
@@ -0,0 +1,50 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ lint:
10
+ name: Lint & Format Check
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.11"
17
+ - run: pip install ruff
18
+ - run: ruff check src tests tools
19
+ - run: ruff format --check src tests tools
20
+
21
+ unit:
22
+ name: Unit Tests (Python ${{ matrix.python-version }})
23
+ runs-on: ubuntu-latest
24
+ strategy:
25
+ fail-fast: false
26
+ matrix:
27
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+ - run: pip install -e .[dev] || (pip install -e . && pip install pytest requests salt)
34
+ - run: PYTHONPATH=src pytest tests/unit -v
35
+
36
+ spec-drift:
37
+ name: Spec Integrity Check
38
+ runs-on: ubuntu-latest
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+ - uses: actions/setup-python@v5
42
+ with:
43
+ python-version: "3.11"
44
+ - run: pip install requests
45
+ - name: Verify Spec Consistency
46
+ run: |
47
+ CORE_REF=$(python3 -c "import json,pathlib; print(json.loads(pathlib.Path('src/saltext/opnsense/utils/controllers.json').read_text()).get('meta',{}).get('core_ref','25.7'))")
48
+ echo "Verifying spec against upstream tag: ${CORE_REF}"
49
+ python tools/generate_spec.py --core-ref "${CORE_REF}" --plugins-ref "${CORE_REF}" --output /tmp/controllers.json
50
+ diff -u tools/controllers.json /tmp/controllers.json || (echo "controllers.json drift detected — run make bump CORE=${CORE_REF}" && exit 1)
@@ -0,0 +1,41 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ name: Build and publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ # Required for Trusted Publishing (OIDC) to PyPI
14
+ id-token: write
15
+ contents: read
16
+
17
+ steps:
18
+ - name: Checkout Repository
19
+ uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # Required for setuptools_scm to determine version from git tags
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.11"
27
+
28
+ - name: Install build tools
29
+ run: python -m pip install --upgrade pip build twine
30
+
31
+ - name: Build sdist and wheel
32
+ run: python -m build
33
+
34
+ - name: Check build artifacts
35
+ run: twine check dist/*
36
+
37
+ - name: Publish to PyPI
38
+ uses: pypa/gh-action-pypi-publish@release/v1
39
+ # If you are using an API token instead of OIDC, uncomment the following:
40
+ # with:
41
+ # password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .eggs/
9
+ .pytest_cache/
10
+ .nox/
11
+ venv/
12
+ .venv/
13
+ controllers.json.bak
14
+ /tmp/
15
+ tools/tmp/
16
+ # generated ergonomic wrappers - dynamic injection covers all, keep repo minimal
17
+ src/saltext/opnsense/modules/opnsense_*.py
18
+ src/saltext/opnsense/states/opnsense_*.py
19
+ # but keep generic opnsense.py (excluded above would ignore generic too? pattern is opnsense_*.py, not opnsense.py, so generic safe)
20
+
@@ -0,0 +1,23 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.14.8
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ types: [python]
8
+ - id: ruff-format
9
+ types: [python]
10
+ - repo: https://github.com/pre-commit/pre-commit-hooks
11
+ rev: v6.0.0
12
+ hooks:
13
+ - id: trailing-whitespace
14
+ - id: end-of-file-fixer
15
+ - id: check-yaml
16
+ - id: check-added-large-files
17
+ args: ['--maxkb=500']
18
+ - id: check-merge-conflict
19
+
20
+ # Setup:
21
+ # pip install pre-commit
22
+ # pre-commit install
23
+ # pre-commit run --all-files
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ This changelog is managed via towncrier.
4
+
5
+ Fragments in `changelog/` (feature, bugfix, doc, removal, misc) are concatenated into this file via `towncrier build`.
6
+
7
+ ## 0.1.0 (unreleased)
8
+
9
+ - Initial scaffold: generic templated `opnsense` execution + state modules, proxy minion, utils client, codegen tool for all API endpoints, unit tests Salt way, examples replacing `query.sh` / `sync-bind-zone.sh`
@@ -0,0 +1,128 @@
1
+ # Contributing — saltext-opnsense
2
+
3
+ ## Quick start
4
+
5
+ ```bash
6
+ python3 -m venv .venv
7
+ source .venv/bin/activate
8
+ pip install -e ".[dev]" # dev: pytest, ruff, towncrier, nox
9
+ # or:
10
+ pip install -e . && pip install pytest ruff towncrier requests "salt>=3008"
11
+
12
+ # generate everything (spec + wrappers + verify + sync)
13
+ make gen-all
14
+ # or manually:
15
+ make gen-spec
16
+ make gen-wrappers
17
+ make verify
18
+ ```
19
+
20
+ ## Running tests
21
+
22
+ ```bash
23
+ # unit (no live OPNsense, mocked)
24
+ PYTHONPATH=src pytest tests/unit -v
25
+
26
+ # import proof: 76 exec + 76 state + 1816 dynamic wrappers
27
+ PYTHONPATH=src python3 tools/verify_import.py
28
+ PYTHONPATH=src python3 tools/verify_import.py
29
+
30
+ # lint
31
+ ruff check src tests tools
32
+ ruff format src tests tools --check
33
+
34
+ # full nox matrix (needs salt installed)
35
+ nox -e tests
36
+ nox -e lint
37
+
38
+ # live smoke (read-only, no Salt) against opnsense-router
39
+ OPNSENSE_HOST=opnsense.example.com OPNSENSE_API_KEY=... OPNSENSE_API_SECRET=... python tools/test_live.py
40
+ # or:
41
+ python tools/test_live.py --host opnsense.example.com --key $KEY --secret $SECRET
42
+
43
+ # integration (gated, live)
44
+ OPNSENSE_LIVE_TEST=1 PYTHONPATH=src pytest tests/integration -v -k live
45
+ ```
46
+
47
+ ## Adding a new test
48
+
49
+ Tests live in `tests/unit/`:
50
+ - `utils/test_client.py` — mock `requests.Session.request`, test `OPNsenseClient.search/get/add`
51
+ - `modules/test_modules_opnsense.py` — mock `_get_client`, test execution module proxy/direct branching
52
+ - `states/test_opnsense.py` — mock `__salt__` (search/add/set/del), test `item_present/absent` idempotency
53
+ - `test_free_modules_import.py` — proves all 76 generated wrappers import
54
+
55
+ Example:
56
+
57
+ ```python
58
+ from unittest.mock import MagicMock, patch
59
+ from saltext.opnsense.utils.opnsense import OPNsenseClient, OPNsenseClientConfig
60
+
61
+ @patch("saltext.opnsense.utils.opnsense.requests.Session.request")
62
+ def test_my_feature(mock_req):
63
+ mock_resp = MagicMock()
64
+ mock_resp.status_code = 200
65
+ mock_resp.json.return_value = {"rows": [], "total": 0}
66
+ mock_resp.text = '{"rows":[]}'
67
+ mock_req.return_value = mock_resp
68
+ cfg = OPNsenseClientConfig(host="opnsense-router", api_key="a", api_secret="b")
69
+ client = OPNsenseClient(cfg)
70
+ res = client.search("unbound", "settings", "host_alias", search_phrase="www")
71
+ assert "rows" in res
72
+ ```
73
+
74
+ Run `pytest tests/unit -v --collect-only` to verify discovery.
75
+
76
+ ## Regenerating code
77
+
78
+ - Spec: `tools/generate_spec.py --core-ref 25.7 --plugins-ref 25.7 --output src/saltext/opnsense/utils/controllers.json`
79
+ - Wrappers: `tools/generate_wrappers.py` (emits 76 exec + 76 state modules)
80
+ - Verify: `tools/verify_import.py`
81
+ `make gen-all` does all three in order.
82
+
83
+ ## Changelog — towncrier
84
+
85
+ We use towncrier. Fragments live in `changelog/`:
86
+
87
+ ```
88
+ changelog.feature. — new features
89
+ changelog.bugfix. — bug fixes
90
+ changelog.doc. — docs
91
+ changelog.removal. — deprecation/removal
92
+ changelog.misc. — trivial (no changelog entry)
93
+ ```
94
+
95
+ Create fragment:
96
+
97
+ ```bash
98
+ towncrier create 123.feature --edit
99
+ # writes changelog/123.feature.md with your text
100
+ # commit it with your PR
101
+ ```
102
+
103
+ Build on release:
104
+
105
+ ```bash
106
+ towncrier build --version 0.2.0
107
+ # appends to CHANGELOG.md, deletes fragments
108
+ ```
109
+
110
+ A changelog fragment is optional for small PRs but encouraged.
111
+
112
+ ## Submitting PR
113
+
114
+ 1. Branch from `main`: `git checkout -b fix/unbound-search`
115
+ 2. Make change + regenerate if needed: `make gen-all`
116
+ 3. Run `PYTHONPATH=src pytest tests/unit -v` and `tools/verify_import.py`
117
+ 4. Run `ruff check src tests tools`
118
+ 5. Add towncrier fragment: `towncrier create <pr>.feature --edit`
119
+ 6. Push, open PR to `main` at `https://github.com/primechuck/saltext-opnsense`. Mention Renovate / OPNsense version if relevant.
120
+
121
+ See `docs/MAINTENANCE.md` for OPNsense release sprint workflow.
122
+
123
+ ## Code style
124
+
125
+ - `ruff` with `line-length=100`, `target-version=py310`
126
+ - Builtins allowed: `__opts__`, `__salt__`, `__proxy__`, `__context__`, `__grains__`, `__utils__` (declared in `pyproject.toml`)
127
+ - No comments unless comstream — rely on docstrings in generated wrappers
128
+ - Prefer `file-based` vs `pip install` note in docs when adding new modules
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 saltext-opnsense Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ include README.md LICENSE CHANGELOG.md
2
+ include src/saltext/opnsense/utils/controllers.json
3
+ include src/saltext/opnsense/utils/models.json
4
+ recursive-include src/saltext/opnsense/utils *.json
5
+ recursive-include tools *.json
6
+ include pyproject.toml
7
+ global-exclude __pycache__
8
+ global-exclude *.py[cod]
9
+ prune .pytest_cache
10
+ prune .nox
@@ -0,0 +1,92 @@
1
+ # Makefile for saltext-opnsense — maintainable codegen pipeline
2
+ # Single entrypoint: make gen-all (wraps tools/generate_all.py)
3
+ # See docs/MAINTENANCE.md for full sprint checklist
4
+
5
+ PYTHON ?= python3
6
+ CORE_REF ?= 25.7
7
+ PLUGINS_REF ?= 25.7
8
+ CORE ?= $(CORE_REF)
9
+ ARGS ?=
10
+ DRY ?=
11
+
12
+ TOOLS_DIR := tools
13
+ SRC_UTILS := src/saltext/opnsense/utils
14
+ SRC_JSON := $(SRC_UTILS)/controllers.json
15
+ SRC_MODELS_JSON := $(SRC_UTILS)/models.json
16
+
17
+ .PHONY: help gen-spec gen-models gen-wrappers bump sync verify test lint gen-all clean
18
+
19
+ help:
20
+ @echo "saltext-opnsense maintenance"
21
+ @echo ""
22
+ @echo "Targets:"
23
+ @echo " gen-spec - Clone core/plugins @ REF and parse controllers.php -> src/.../utils/controllers.json"
24
+ @echo " gen-models - Parse Model XML -> src/.../utils/models.json"
25
+ @echo " gen-wrappers - Spec -> 76 exec + 76 state wrappers (auto-generated)"
26
+ @echo " bump - Upstream version sprint: make bump CORE=25.7"
27
+ @echo " sync - Copy src -> extmods directories for gitfs file-based install"
28
+ @echo " verify - Prove all 76 modules import (exec+state+dynamic)"
29
+ @echo " test - pytest tests/unit -q"
30
+ @echo " lint - ruff check src tests tools"
31
+ @echo " gen-all - Full pipeline: spec -> wrappers -> sync -> verify -> test (via generate_all.py)"
32
+ @echo " clean - Remove caches, /tmp/opnsense-spec, pycache"
33
+ @echo ""
34
+ @echo "Variables:"
35
+ @echo " CORE_REF, PLUGINS_REF (default 25.7) e.g. make gen-all CORE_REF=25.7 PLUGINS_REF=25.7"
36
+ @echo " CORE (alias for CORE_REF/PLUGINS_REF) e.g. make bump CORE=25.7"
37
+ @echo ""
38
+ @echo "Examples:"
39
+ @echo " make bump CORE=25.7"
40
+ @echo " make gen-all CORE_REF=25.7 PLUGINS_REF=25.7"
41
+ @echo " make gen-wrappers && make verify"
42
+
43
+ gen-spec:
44
+ @mkdir -p $(SRC_UTILS)
45
+ $(PYTHON) $(TOOLS_DIR)/generate_spec.py --core-ref $(CORE_REF) --plugins-ref $(PLUGINS_REF) --output $(SRC_JSON)
46
+ @jq .meta $(SRC_JSON) 2>/dev/null || python3 -c "import json,pathlib; print(json.loads(pathlib.Path('$(SRC_JSON)').read_text()).get('meta'))"
47
+
48
+ gen-models:
49
+ @mkdir -p $(SRC_UTILS)
50
+ @if [ -d /tmp/opnsense-spec/core ] && [ -d /tmp/opnsense-spec/plugins ]; then \
51
+ echo "Using cached clones /tmp/opnsense-spec/core and /tmp/opnsense-spec/plugins"; \
52
+ $(PYTHON) $(TOOLS_DIR)/generate_models.py --core /tmp/opnsense-spec/core --plugins /tmp/opnsense-spec/plugins --output $(SRC_MODELS_JSON); \
53
+ else \
54
+ $(PYTHON) $(TOOLS_DIR)/generate_models.py --core-ref $(CORE_REF) --plugins-ref $(PLUGINS_REF) --output $(SRC_MODELS_JSON); \
55
+ fi
56
+ @echo "Wrote $(SRC_MODELS_JSON)"
57
+
58
+ gen-wrappers:
59
+ $(PYTHON) $(TOOLS_DIR)/generate_wrappers.py
60
+
61
+ bump:
62
+ $(PYTHON) $(TOOLS_DIR)/generate_spec.py --core-ref $(CORE) --plugins-ref $(CORE) --output $(SRC_JSON)
63
+ cp $(SRC_JSON) $(TOOLS_DIR)/controllers.json
64
+ $(PYTHON) $(TOOLS_DIR)/generate_wrappers.py
65
+ PYTHONPATH=src $(PYTHON) $(TOOLS_DIR)/verify_import.py
66
+
67
+ sync:
68
+ $(PYTHON) $(TOOLS_DIR)/sync_extmods.py --copy
69
+
70
+ verify:
71
+ PYTHONPATH=src $(PYTHON) $(TOOLS_DIR)/verify_import.py
72
+
73
+ test:
74
+ PYTHONPATH=src $(PYTHON) -m pytest tests/unit -q
75
+
76
+ lint:
77
+ $(PYTHON) -m ruff check src tests tools || ruff check src tests tools
78
+
79
+ gen-all:
80
+ ifeq ($(DRY),1)
81
+ $(PYTHON) $(TOOLS_DIR)/generate_all.py --core-ref $(CORE_REF) --plugins-ref $(PLUGINS_REF) --dry-run $(ARGS)
82
+ else
83
+ $(PYTHON) $(TOOLS_DIR)/generate_all.py --core-ref $(CORE_REF) --plugins-ref $(PLUGINS_REF) $(ARGS)
84
+ endif
85
+
86
+ clean:
87
+ rm -rf /tmp/opnsense-spec tools/tmp __pycache__ src/__pycache__ .pytest_cache .nox build dist *.egg-info src/*.egg-info
88
+ rm -rf src/saltext/opnsense/__pycache__ src/saltext/opnsense/modules/__pycache__ src/saltext/opnsense/states/__pycache__ src/saltext/opnsense/utils/__pycache__
89
+ rm -rf src/saltext/opnsense/proxy/__pycache__ src/saltext/opnsense/grains/__pycache__ tests/__pycache__ tests/unit/__pycache__
90
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
91
+ find . -type f -name "*.pyc" -delete 2>/dev/null || true
92
+ @echo "Cleaned caches. Generated wrappers/json kept."
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: saltext-opnsense
3
+ Version: 0.1.1.dev0
4
+ Summary: Salt extension for managing OPNsense via its API - templated, 3008+ ready, with dynamic wrappers, file-based install, and Vault support
5
+ Author-email: David Bierce <david@bierce.org>
6
+ Maintainer-email: David Bierce <david@bierce.org>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/primechuck/saltext-opnsense
9
+ Project-URL: Repository, https://github.com/primechuck/saltext-opnsense
10
+ Project-URL: Issues, https://github.com/primechuck/saltext-opnsense/issues
11
+ Project-URL: Documentation, https://primechuck.github.io/saltext-opnsense/
12
+ Keywords: salt,salt-extension,saltext,opnsense,firewall,api,unbound,bind,kea,acme
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Topic :: System :: Networking :: Firewalls
17
+ Classifier: Topic :: System :: Systems Administration
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3 :: Only
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: salt>=3008
30
+ Requires-Dist: requests>=2.28
31
+ Requires-Dist: urllib3>=1.26
32
+ Dynamic: license-file
33
+
34
+ # saltext-opnsense
35
+
36
+ SaltStack extension for managing OPNsense firewalls via the REST API.
37
+
38
+ Manage OPNsense services (Unbound DNS, Kea DHCP, BIND, ACME certs, firewall aliases, interfaces) declaratively with Salt states or programmatically via execution modules. API bindings are generated directly from upstream OPNsense schemas.
39
+
40
+ > **Target Release**: Built for **OPNsense 25.7** (76 modules, ~1,816 API endpoints).
41
+ > **Core Design Goal**: Maintainer laziness. Never hand-code API wrappers. When OPNsense ships a new release, all 76 modules and 1,800+ endpoints are regenerated directly from upstream schemas via `make bump CORE=25.7`.
42
+
43
+
44
+ ## Features
45
+
46
+ - **Execution Modules**: Direct API calls to OPNsense controllers and actions.
47
+ - **State Modules**: Declarative states for OPNsense resources (`item_present`, `item_absent`, DNS aliases, DHCP leases, ACME certs).
48
+ - **Proxy Minion Support**: Agentless management of OPNsense hardware and VMs.
49
+ - **Auto-Generated Spec**: Keeps up with upstream OPNsense releases without manual code edits.
50
+ - **Diagnostics (`opnsense.doctor`)**: Quick CLI check for credentials, API connectivity, and firmware status.
51
+
52
+ ## Quick Start
53
+
54
+ ### 1. Installation
55
+
56
+ Install on the Salt Master and Proxy Minion:
57
+
58
+ ```bash
59
+ salt-pip install saltext-opnsense
60
+ salt '*' saltutil.sync_all
61
+ ```
62
+
63
+ Or copy directly into Salt's `file_roots` (for environments without `salt-pip`):
64
+
65
+ ```bash
66
+ python3 tools/sync_extmods.py --copy
67
+ salt '*' saltutil.sync_all
68
+ ```
69
+
70
+ ### 2. Configuration
71
+
72
+ Define your OPNsense target in Pillar (e.g. `/srv/pillar/opnsense.sls`). See [pillar.example](file:///Users/dbierce/GitHub/configurations/projects/saltext-opnsense-review/pillar.example) for details.
73
+
74
+ ```yaml
75
+ proxy:
76
+ proxytype: opnsense
77
+ host: opnsense.example.com
78
+ proto: https
79
+ api_key: "your_api_key"
80
+ api_secret: "your_api_secret"
81
+ # verify_ssl: false # Optional; defaults to true
82
+ ```
83
+
84
+ ### 3. Diagnostics
85
+
86
+ Verify connectivity and credential resolution:
87
+
88
+ ```bash
89
+ salt opnsense-router opnsense.doctor
90
+ ```
91
+
92
+ ## Usage
93
+
94
+ ### Execution Module
95
+
96
+ ```bash
97
+ # Search Unbound DNS host aliases
98
+ salt opnsense-router opnsense.search unbound settings host_alias
99
+
100
+ # Call endpoint directly
101
+ salt opnsense-router opnsense_unbound.search_host_alias
102
+ ```
103
+
104
+ ### State Module
105
+
106
+ ```yaml
107
+ # Ensure an Unbound Host Alias exists
108
+ www_alias:
109
+ opnsense_unbound.host_alias_present:
110
+ - data:
111
+ enabled: "1"
112
+ hostname: www
113
+ domain: example.com
114
+ - reconfigure: unbound/service/reconfigure
115
+ ```
116
+
117
+ ## Maintenance & Upgrades
118
+
119
+ API spec bindings are generated from upstream `opnsense/core` and `opnsense/plugins`.
120
+
121
+ When OPNsense ships a new release (e.g. `26.1`), regenerate bindings with:
122
+
123
+ ```bash
124
+ make bump CORE=26.1
125
+ ```
126
+
127
+ For developer documentation and full maintenance details, see [docs/MAINTENANCE.md](file:///Users/dbierce/GitHub/configurations/projects/saltext-opnsense-review/docs/MAINTENANCE.md).
128
+
129
+ ## Testing
130
+
131
+ ```bash
132
+ # Run unit tests
133
+ PYTHONPATH=src pytest tests/unit -v
134
+
135
+ # Verify module imports
136
+ PYTHONPATH=src python3 tools/verify_import.py
137
+ ```
@@ -0,0 +1,104 @@
1
+ # saltext-opnsense
2
+
3
+ SaltStack extension for managing OPNsense firewalls via the REST API.
4
+
5
+ Manage OPNsense services (Unbound DNS, Kea DHCP, BIND, ACME certs, firewall aliases, interfaces) declaratively with Salt states or programmatically via execution modules. API bindings are generated directly from upstream OPNsense schemas.
6
+
7
+ > **Target Release**: Built for **OPNsense 25.7** (76 modules, ~1,816 API endpoints).
8
+ > **Core Design Goal**: Maintainer laziness. Never hand-code API wrappers. When OPNsense ships a new release, all 76 modules and 1,800+ endpoints are regenerated directly from upstream schemas via `make bump CORE=25.7`.
9
+
10
+
11
+ ## Features
12
+
13
+ - **Execution Modules**: Direct API calls to OPNsense controllers and actions.
14
+ - **State Modules**: Declarative states for OPNsense resources (`item_present`, `item_absent`, DNS aliases, DHCP leases, ACME certs).
15
+ - **Proxy Minion Support**: Agentless management of OPNsense hardware and VMs.
16
+ - **Auto-Generated Spec**: Keeps up with upstream OPNsense releases without manual code edits.
17
+ - **Diagnostics (`opnsense.doctor`)**: Quick CLI check for credentials, API connectivity, and firmware status.
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Installation
22
+
23
+ Install on the Salt Master and Proxy Minion:
24
+
25
+ ```bash
26
+ salt-pip install saltext-opnsense
27
+ salt '*' saltutil.sync_all
28
+ ```
29
+
30
+ Or copy directly into Salt's `file_roots` (for environments without `salt-pip`):
31
+
32
+ ```bash
33
+ python3 tools/sync_extmods.py --copy
34
+ salt '*' saltutil.sync_all
35
+ ```
36
+
37
+ ### 2. Configuration
38
+
39
+ Define your OPNsense target in Pillar (e.g. `/srv/pillar/opnsense.sls`). See [pillar.example](file:///Users/dbierce/GitHub/configurations/projects/saltext-opnsense-review/pillar.example) for details.
40
+
41
+ ```yaml
42
+ proxy:
43
+ proxytype: opnsense
44
+ host: opnsense.example.com
45
+ proto: https
46
+ api_key: "your_api_key"
47
+ api_secret: "your_api_secret"
48
+ # verify_ssl: false # Optional; defaults to true
49
+ ```
50
+
51
+ ### 3. Diagnostics
52
+
53
+ Verify connectivity and credential resolution:
54
+
55
+ ```bash
56
+ salt opnsense-router opnsense.doctor
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ ### Execution Module
62
+
63
+ ```bash
64
+ # Search Unbound DNS host aliases
65
+ salt opnsense-router opnsense.search unbound settings host_alias
66
+
67
+ # Call endpoint directly
68
+ salt opnsense-router opnsense_unbound.search_host_alias
69
+ ```
70
+
71
+ ### State Module
72
+
73
+ ```yaml
74
+ # Ensure an Unbound Host Alias exists
75
+ www_alias:
76
+ opnsense_unbound.host_alias_present:
77
+ - data:
78
+ enabled: "1"
79
+ hostname: www
80
+ domain: example.com
81
+ - reconfigure: unbound/service/reconfigure
82
+ ```
83
+
84
+ ## Maintenance & Upgrades
85
+
86
+ API spec bindings are generated from upstream `opnsense/core` and `opnsense/plugins`.
87
+
88
+ When OPNsense ships a new release (e.g. `26.1`), regenerate bindings with:
89
+
90
+ ```bash
91
+ make bump CORE=26.1
92
+ ```
93
+
94
+ For developer documentation and full maintenance details, see [docs/MAINTENANCE.md](file:///Users/dbierce/GitHub/configurations/projects/saltext-opnsense-review/docs/MAINTENANCE.md).
95
+
96
+ ## Testing
97
+
98
+ ```bash
99
+ # Run unit tests
100
+ PYTHONPATH=src pytest tests/unit -v
101
+
102
+ # Verify module imports
103
+ PYTHONPATH=src python3 tools/verify_import.py
104
+ ```
@@ -0,0 +1,10 @@
1
+ # Changelog fragments
2
+
3
+ Use towncrier:
4
+
5
+ ```bash
6
+ towncrier create 123.feature --edit
7
+ towncrier build --version 0.1.0
8
+ ```
9
+
10
+ Categories: feature, bugfix, doc, removal, misc