mreg-api 0.3.0__tar.gz → 0.4.0__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 (90) hide show
  1. mreg_api-0.4.0/.github/workflows/docs.yml +29 -0
  2. {mreg_api-0.3.0 → mreg_api-0.4.0}/.markdownlint.json +5 -1
  3. {mreg_api-0.3.0 → mreg_api-0.4.0}/CHANGELOG.md +32 -1
  4. {mreg_api-0.3.0 → mreg_api-0.4.0}/PKG-INFO +23 -2
  5. mreg_api-0.4.0/README.md +44 -0
  6. {mreg_api-0.3.0 → mreg_api-0.4.0}/TESTING.md +27 -11
  7. {mreg_api-0.3.0 → mreg_api-0.4.0}/ci/docker-compose.yml +1 -0
  8. {mreg_api-0.3.0 → mreg_api-0.4.0}/ci/run_tests.sh +31 -4
  9. mreg_api-0.4.0/docs/guides/authentication.md +62 -0
  10. mreg_api-0.4.0/docs/guides/caching.md +63 -0
  11. mreg_api-0.4.0/docs/guides/configuration.md +64 -0
  12. mreg_api-0.4.0/docs/guides/eventlog.md +52 -0
  13. mreg_api-0.4.0/docs/guides/requesthistory.md +15 -0
  14. mreg_api-0.4.0/docs/guides/resources.md +163 -0
  15. mreg_api-0.4.0/docs/index.md +50 -0
  16. mreg_api-0.4.0/docs/quick-start.md +122 -0
  17. mreg_api-0.4.0/docs/reference/cache.md +15 -0
  18. mreg_api-0.4.0/docs/reference/client.md +14 -0
  19. mreg_api-0.4.0/docs/reference/events.md +25 -0
  20. mreg_api-0.4.0/docs/reference/exceptions.md +12 -0
  21. mreg_api-0.4.0/docs/reference/managers.md +123 -0
  22. mreg_api-0.4.0/docs/reference/models.md +11 -0
  23. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/_version.py +3 -3
  24. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/client.py +63 -44
  25. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/events.py +38 -5
  26. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/managers.py +407 -231
  27. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/models/models.py +20 -16
  28. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/PKG-INFO +23 -2
  29. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/SOURCES.txt +17 -0
  30. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/scm_file_list.json +18 -1
  31. mreg_api-0.4.0/mreg_api.egg-info/scm_version.json +8 -0
  32. {mreg_api-0.3.0 → mreg_api-0.4.0}/pyproject.toml +2 -1
  33. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_atoms.py +26 -40
  34. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_cname.py +1 -1
  35. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_host_records.py +13 -13
  36. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_hosts.py +1 -8
  37. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_ip.py +0 -4
  38. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_labels.py +10 -17
  39. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_meta.py +4 -0
  40. mreg_api-0.4.0/tests/integration/test_nameservers.py +130 -0
  41. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_network_policy.py +0 -15
  42. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_networks.py +10 -36
  43. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_client.py +1 -0
  44. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_events.py +15 -15
  45. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_managers.py +42 -0
  46. {mreg_api-0.3.0 → mreg_api-0.4.0}/uv.lock +291 -5
  47. mreg_api-0.4.0/zensical.toml +398 -0
  48. mreg_api-0.3.0/README.md +0 -23
  49. mreg_api-0.3.0/mreg_api.egg-info/scm_version.json +0 -8
  50. {mreg_api-0.3.0 → mreg_api-0.4.0}/.claude/CLAUDE.md +0 -0
  51. {mreg_api-0.3.0 → mreg_api-0.4.0}/.github/workflows/publish.yml +0 -0
  52. {mreg_api-0.3.0 → mreg_api-0.4.0}/.github/workflows/test.yml +0 -0
  53. {mreg_api-0.3.0 → mreg_api-0.4.0}/.gitignore +0 -0
  54. {mreg_api-0.3.0 → mreg_api-0.4.0}/.pre-commit-config.yaml +0 -0
  55. {mreg_api-0.3.0 → mreg_api-0.4.0}/LICENSE +0 -0
  56. {mreg_api-0.3.0 → mreg_api-0.4.0}/NOTES.md +0 -0
  57. {mreg_api-0.3.0 → mreg_api-0.4.0}/ci/Dockerfile +0 -0
  58. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/__about__.py +0 -0
  59. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/__init__.py +0 -0
  60. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/cache.py +0 -0
  61. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/endpoints.py +0 -0
  62. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/exceptions.py +0 -0
  63. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/models/__init__.py +0 -0
  64. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/models/abstracts.py +0 -0
  65. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/models/fields.py +0 -0
  66. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/models/history.py +0 -0
  67. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/py.typed +0 -0
  68. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/types.py +0 -0
  69. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/utilities/__init__.py +0 -0
  70. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/utilities/fs.py +0 -0
  71. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api/utilities/shared.py +0 -0
  72. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/dependency_links.txt +0 -0
  73. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/requires.txt +0 -0
  74. {mreg_api-0.3.0 → mreg_api-0.4.0}/mreg_api.egg-info/top_level.txt +0 -0
  75. {mreg_api-0.3.0 → mreg_api-0.4.0}/setup.cfg +0 -0
  76. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/__init__.py +0 -0
  77. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/conftest.py +0 -0
  78. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/__init__.py +0 -0
  79. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/conftest.py +0 -0
  80. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_dhcp.py +0 -0
  81. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_hostgroups.py +0 -0
  82. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_permissions.py +0 -0
  83. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_roles.py +0 -0
  84. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/integration/test_zones.py +0 -0
  85. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/models/__init__.py +0 -0
  86. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/models/test_fields.py +0 -0
  87. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/models/test_models.py +0 -0
  88. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_cache.py +0 -0
  89. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_exceptions.py +0 -0
  90. {mreg_api-0.3.0 → mreg_api-0.4.0}/tests/test_types.py +0 -0
@@ -0,0 +1,29 @@
1
+ name: Documentation
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ permissions:
7
+ contents: read
8
+ pages: write
9
+ id-token: write
10
+ jobs:
11
+ deploy:
12
+ environment:
13
+ name: github-pages
14
+ url: ${{ steps.deployment.outputs.page_url }}
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/configure-pages@v6
18
+ - uses: actions/checkout@v6
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v2
21
+ - name: Set up Python 3.12
22
+ run: uv python install 3.12
23
+ - run: uv sync --only-group docs
24
+ - run: uv run zensical build --clean
25
+ - uses: actions/upload-pages-artifact@v5
26
+ with:
27
+ path: site
28
+ - uses: actions/deploy-pages@v5
29
+ id: deployment
@@ -5,5 +5,9 @@
5
5
  },
6
6
  "line-length": false,
7
7
  "no-bare-urls": false,
8
- "no-inline-html": false
8
+ "no-inline-html": false,
9
+ "MD046": false,
10
+ "MD056": {
11
+ "severity": "warning"
12
+ }
9
13
  }
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  <!-- ## Unreleased -->
9
9
 
10
+ ## [0.4.0](https://github.com/unioslo/mreg-api/releases/tag/0.4.0) - 2026-08-24
11
+
12
+ ### Added
13
+
14
+ - `MregClient.community` property to access the `CommunityManager` for managing communities.
15
+ - Still exists via `MregClient.network.community`.
16
+ - `EventLog.get(subject=..., kind=..., level=..., min_level=...)` method to support retrieving events and filtering by a combination of subject, kind, and level. This replaces the existing `get_for`, `get_by_kind`, `get_by_level`, and `get_at_or_above` methods, and allows one to combine all their filters in a single call. Currently, only intersections of filters are supported (i.e. events must match all filters to be returned). Future releases may support unions of filters (i.e. events matching any filter will be returned).
17
+ - `MregClient.policy` property that groups the existing `MregClient.atom`, `MregClient.role`, `MregClient.label` into a common namespace as `MregClient.policy.role`, `MregClient.policy.atom`, and `MregClient.policy.label`.
18
+
19
+ ### Changed
20
+
21
+ - `MregClient.*.create()` semantics and return type changes:
22
+ - POST requests now prefer to return the created object found in the response, rather than fetching the object again from the API via the location header. The manager falls back on fetching via location header if the response does not contain the created object.
23
+ - `create()` method return type changed from `T | None` to `T`. Never returns None.
24
+ - `create(fetch_after_create)` parameter removed.
25
+ - `models.LDAPHealth` now defines `status` as a `Literal["OK", "Down", "Unknown"]` type instead of a generic string.
26
+ - `models.UserInfo` now has defaults for all its fields.
27
+ - `MregClient.community.create()` now returns the created `Community` object instead of a boolean indicating success.
28
+ - Default limit of 500 for `list()` calls has been changed to `None` (unrestricted).
29
+
30
+ ### Removed
31
+
32
+ - **BREAKING:** `create(fetch_after_create)` parameter. No longer has any meaning as each endpoint returns a valid object representation in the response body after creation.
33
+
34
+ ### Deprecated
35
+
36
+ - `EventLog.get_all()` -> `EventLog.get()`
37
+ - `EventLog.get_for()` -> `EventLog.get(subject=...)`
38
+ - `EventLog.get_by_kind()` -> `EventLog.get(kind=...)`
39
+ - `EventLog.get_by_level()` -> `EventLog.get(level=...)`
40
+ - `EventLog.get_at_or_above()` -> `EventLog.get(min_level=...)`
41
+
10
42
  ## [0.3.0](https://github.com/unioslo/mreg-api/releases/tag/0.3.0) - 2026-08-12
11
43
 
12
44
  ### Added
@@ -19,7 +51,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
19
51
  - **BREAKING**: `MregClient` is no longer a singleton. Each instance is independent and maintains its own state. The `MregClient.get_instance()` method has been removed. Each instantiation of `MregClient` is now independent and maintains its own state, including history, events and cache.
20
52
  - `Network.get_community()` now ignores case when searching for communities by name. It returns the first community with the given name, or None if not found.
21
53
 
22
-
23
54
  ### Removed
24
55
 
25
56
  - **BREAKING**: `MregClient.reset_instance` removed because the singleton pattern has been removed.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mreg-api
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: MREG API
5
5
  Author-email: Terje Kvernes <terjekv@uio.no>
6
6
  Maintainer-email: Peder Hovdan Andresen <pederhan@uio.no>
@@ -701,7 +701,28 @@ Dynamic: license-file
701
701
 
702
702
  # MREG API [![Build Status](https://github.com/unioslo/mreg-api/actions/workflows/test.yml/badge.svg)](https://github.com/unioslo/mreg-api/actions/workflows/test.yml)
703
703
 
704
- ## Pre-commit Hooks
704
+ `mreg-api` is a Python client library for the [MREG](https://github.com/unioslo/mreg)
705
+ REST API. It gives you a typed, ergonomic interface to every MREG
706
+ resource through a single client
707
+ object with scoped namespaces for each resource type.
708
+
709
+ It provides optional caching of resources, automatic FQDN expansion of hostnames, and a consistent interface for all resource types. The client is compatible with Python 3.11 and later.
710
+
711
+
712
+ ## Documentation
713
+
714
+ https://unioslo.github.io/mreg-api/
715
+
716
+ ## Development
717
+
718
+ Set up a development environment with `uv`:
719
+
720
+ ```bash
721
+ git clone git@github.com:unioslo/mreg-api.git
722
+ uv sync
723
+ ```
724
+
725
+ ### Pre-commit Hooks
705
726
 
706
727
  This project uses `prek` to manage pre-commit hooks for code quality and formatting. To set up the pre-commit hooks, run the following command:
707
728
 
@@ -0,0 +1,44 @@
1
+ # MREG API [![Build Status](https://github.com/unioslo/mreg-api/actions/workflows/test.yml/badge.svg)](https://github.com/unioslo/mreg-api/actions/workflows/test.yml)
2
+
3
+ `mreg-api` is a Python client library for the [MREG](https://github.com/unioslo/mreg)
4
+ REST API. It gives you a typed, ergonomic interface to every MREG
5
+ resource through a single client
6
+ object with scoped namespaces for each resource type.
7
+
8
+ It provides optional caching of resources, automatic FQDN expansion of hostnames, and a consistent interface for all resource types. The client is compatible with Python 3.11 and later.
9
+
10
+
11
+ ## Documentation
12
+
13
+ https://unioslo.github.io/mreg-api/
14
+
15
+ ## Development
16
+
17
+ Set up a development environment with `uv`:
18
+
19
+ ```bash
20
+ git clone git@github.com:unioslo/mreg-api.git
21
+ uv sync
22
+ ```
23
+
24
+ ### Pre-commit Hooks
25
+
26
+ This project uses `prek` to manage pre-commit hooks for code quality and formatting. To set up the pre-commit hooks, run the following command:
27
+
28
+ ```bash
29
+ uv tool install prek
30
+ ```
31
+
32
+ Then, install the pre-commit hooks with:
33
+
34
+ ```bash
35
+ prek install
36
+ ```
37
+
38
+ Run the pre-commit checks manually with:
39
+
40
+ ```bash
41
+ prek run
42
+ # Optionally for all files:
43
+ prek run --all-files
44
+ ```
@@ -45,11 +45,22 @@ Flags:
45
45
  | `--unit-only` | Skip integration tests (no containers started) |
46
46
  | `--integration-only` | Skip unit tests |
47
47
  | `--no-cov` | Disable coverage. Used in CI |
48
+ | `-h`, `--help` | Show usage |
49
+ | `-- ARGS...` | Pass everything after `--` to pytest |
50
+
51
+ Unknown flags are an error (exit code 2) — the script never silently ignores them.
52
+
53
+ Container setup (`ci/run_tests.sh` only, not read by pytest):
54
+
55
+ | Env var | Default | Description |
56
+ |---|---|---|
57
+ | `MREG_IMAGE` | `ghcr.io/unioslo/mreg:master` | mreg container image |
58
+ | `MREG_IMAGE_PULL_POLICY` | `missing` | Compose pull policy: `missing`, `always`, `never` |
59
+ | `MREG_PORT` | `8000` | Host port the mreg container is exposed on |
60
+
61
+ `master` is a mutable tag, so a local image can go stale. Use `MREG_IMAGE_PULL_POLICY=always` to pull the current one.
62
+
48
63
 
49
- ```bash
50
- # Fast run without coverage
51
- bash ci/run_tests.sh --no-cov
52
- ```
53
64
 
54
65
  ### Running manually against a local server
55
66
 
@@ -88,19 +99,24 @@ uv run pytest tests/integration/ \
88
99
  CLI flags take precedence over env vars.
89
100
 
90
101
 
91
- ### Subset runs
102
+ ### Subset and extra arguments
103
+
92
104
 
93
105
  ```bash
94
- # Read-only tests only (safe against staging/production)
95
- uv run pytest tests/integration/ -m readonly
106
+ # Fast run without coverage
107
+ bash ci/run_tests.sh --no-cov
96
108
 
97
- # Single resource type
98
- uv run pytest tests/integration/test_labels.py
109
+ # Single module
110
+ bash ci/run_tests.sh --integration-only -- tests/integration/test_labels.py
99
111
 
100
- # Specific test
101
- uv run pytest tests/integration/test_labels.py::test_delete_by_name
112
+ # Stop on first failure, filter by name
113
+ bash ci/run_tests.sh --integration-only -- -x -k labels
102
114
  ```
103
115
 
116
+ Each pass selects its tests by marker (`-m integration` / `-m "not integration"`) rather than by
117
+ path, so a path after `--` narrows the run. When both suites run, the arguments go to both pytest
118
+ invocations.
119
+
104
120
  ## Coverage
105
121
 
106
122
  ### Unit tests only
@@ -13,6 +13,7 @@ services:
13
13
 
14
14
  mreg:
15
15
  image: ${MREG_IMAGE:-ghcr.io/unioslo/mreg:master}
16
+ pull_policy: ${MREG_IMAGE_PULL_POLICY:-missing}
16
17
  container_name: mreg
17
18
  depends_on:
18
19
  postgres:
@@ -8,6 +8,7 @@ RUN_UNIT=true
8
8
  RUN_INTEGRATION=true
9
9
  RUN_COVERAGE=true
10
10
  MREG_IMAGE="${MREG_IMAGE:-ghcr.io/unioslo/mreg:master}"
11
+ MREG_IMAGE_PULL_POLICY="${MREG_IMAGE_PULL_POLICY:-missing}"
11
12
  # Host port the mreg container is exposed on. Override if 8000 is already in use.
12
13
  MREG_PORT="${MREG_PORT:-8000}"
13
14
  MREG_URL="${MREG_URL:-http://127.0.0.1:${MREG_PORT}}"
@@ -15,12 +16,32 @@ MREG_USERNAME="${MREG_USERNAME:-test}"
15
16
  MREG_PASSWORD="${MREG_PASSWORD:-test}"
16
17
  MREG_CACHE="${MREG_CACHE:-0}"
17
18
 
19
+ usage() {
20
+ cat <<'EOF'
21
+ Usage: bash ci/run_tests.sh [--unit-only|--integration-only] [--no-cov] [-- pytest args...]
22
+
23
+ Everything after -- is passed to pytest:
24
+
25
+ bash ci/run_tests.sh --integration-only -- tests/integration/test_labels.py
26
+ bash ci/run_tests.sh --integration-only -- -x -k labels
27
+ EOF
28
+ }
29
+
30
+ # Extra arguments passed to pytest (everything after --).
31
+ EXTRA_ARGS=()
32
+
18
33
  while [[ $# -gt 0 ]]; do
19
34
  case $1 in
20
35
  --unit-only) RUN_INTEGRATION=false; shift ;;
21
36
  --integration-only) RUN_UNIT=false; shift ;;
22
37
  --no-cov) RUN_COVERAGE=false; shift ;;
23
- *) shift ;;
38
+ -h|--help) usage; exit 0 ;;
39
+ --) shift; EXTRA_ARGS=("$@"); break ;;
40
+ *)
41
+ echo "ERROR: unknown option: $1" >&2
42
+ usage >&2
43
+ exit 2
44
+ ;;
24
45
  esac
25
46
  done
26
47
 
@@ -47,7 +68,9 @@ if [[ "$RUN_INTEGRATION" == "true" ]]; then
47
68
  cd "$SCRIPT_DIR"
48
69
 
49
70
  echo "Starting mreg and postgres on port ${MREG_PORT}..."
50
- MREG_IMAGE="$MREG_IMAGE" MREG_PORT="$MREG_PORT" $DOCKER compose up -d
71
+ MREG_IMAGE="$MREG_IMAGE" MREG_PORT="$MREG_PORT" \
72
+ MREG_IMAGE_PULL_POLICY="$MREG_IMAGE_PULL_POLICY" \
73
+ $DOCKER compose up -d
51
74
 
52
75
  echo "Creating superuser..."
53
76
  $DOCKER exec mreg uv run /app/manage.py create_mreg_superuser \
@@ -65,23 +88,27 @@ INTEGRATION_EXIT=0
65
88
 
66
89
  if [[ "$RUN_UNIT" == "true" ]]; then
67
90
  echo "Running unit tests..."
68
- UNIT_ARGS=(tests/ --ignore=tests/integration -v)
91
+ # No path here: pytest falls back to testpaths (tests/) from pyproject.toml,
92
+ # so a path in EXTRA_ARGS narrows the run instead of being added to it.
93
+ UNIT_ARGS=(-m "not integration" -v)
69
94
  if [[ "$RUN_COVERAGE" == "true" ]]; then
70
95
  UNIT_ARGS+=(--cov=mreg_api --cov-report=)
71
96
  else
72
97
  UNIT_ARGS+=(--no-cov)
73
98
  fi
99
+ UNIT_ARGS+=(${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"})
74
100
  uv run pytest "${UNIT_ARGS[@]}" || UNIT_EXIT=$?
75
101
  fi
76
102
 
77
103
  if [[ "$RUN_INTEGRATION" == "true" ]]; then
78
104
  echo "Running integration tests..."
79
- INTEGRATION_ARGS=(tests/integration/ -v)
105
+ INTEGRATION_ARGS=(-m integration -v)
80
106
  if [[ "$RUN_COVERAGE" == "true" ]]; then
81
107
  INTEGRATION_ARGS+=(--cov=mreg_api --cov-append --cov-report=html --cov-report=term)
82
108
  else
83
109
  INTEGRATION_ARGS+=(--no-cov)
84
110
  fi
111
+ INTEGRATION_ARGS+=(${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"})
85
112
  MREG_URL="$MREG_URL" \
86
113
  MREG_USERNAME="$MREG_USERNAME" \
87
114
  MREG_PASSWORD="$MREG_PASSWORD" \
@@ -0,0 +1,62 @@
1
+ ---
2
+ icon: lucide/key-round
3
+ ---
4
+
5
+ # Authentication
6
+
7
+ The client does not authenticate on construction and never reads credentials from the
8
+ environment or a token file on its own — authentication is always explicit. There are two
9
+ ways to authenticate.
10
+
11
+ ## Username and password
12
+
13
+ [`login()`][mreg_api.client.MregClient.login] exchanges credentials for a token, stores
14
+ it on the client, and returns it. Reading credentials from the environment is a common
15
+ pattern:
16
+
17
+ ```python
18
+ import os
19
+ from mreg_api import MregClient
20
+
21
+ client = MregClient(url="https://mreg.example.com", domain="example.com")
22
+ client.login(
23
+ username=os.environ["MREG_USERNAME"],
24
+ password=os.environ["MREG_PASSWORD"],
25
+ )
26
+ ```
27
+
28
+ `login()` raises [`LoginFailedError`][mreg_api.exceptions.LoginFailedError] on a
29
+ connection failure or bad credentials.
30
+
31
+ ## Existing token
32
+
33
+ !!! note
34
+
35
+ Token auth is primarily relevant to persistent sessions for applications such as [mreg-cli](https://github.com/unioslo/mreg-cli), not for scripts or ephemeral sessions.
36
+
37
+ If you already have a token, set it directly with
38
+ [`set_token()`][mreg_api.client.MregClient.set_token] — no `login()` call needed:
39
+
40
+ ```python
41
+ client = MregClient(url="https://mreg.example.com")
42
+ client.set_token(os.environ["MREG_TOKEN"])
43
+ ```
44
+
45
+ ## Managing the token
46
+
47
+ ```python
48
+ client.get_token() # current token, or None
49
+ client.test_auth() # raises InvalidAuthTokenError if the token is invalid
50
+ client.unset_token() # clear the token locally
51
+ client.logout() # invalidate the token on the server
52
+ ```
53
+
54
+ ## Correlation IDs
55
+
56
+ To make requests easier to trace in server logs, attach a correlation ID that is sent
57
+ with every subsequent request:
58
+
59
+ ```python
60
+ client.set_correlation_id("nightly-sync")
61
+ client.get_correlation_id()
62
+ ```
@@ -0,0 +1,63 @@
1
+ ---
2
+ icon: lucide/database
3
+ ---
4
+
5
+ # Caching
6
+
7
+ The client can cache `GET` responses on disk to avoid refetching unchanged data. Caching
8
+ is **off by default**. Any successful `POST`/`PATCH`/`DELETE` clears the cache, so writes
9
+ never leave you reading stale data.
10
+
11
+ ## Enabling at construction
12
+
13
+ Pass `cache=True` for defaults, or a [`CacheConfig`][mreg_api.cache.CacheConfig] to
14
+ customize:
15
+
16
+ ```python
17
+ from mreg_api import MregClient, CacheConfig
18
+
19
+ # Defaults
20
+ client = MregClient(url="https://mreg.example.com", cache=True)
21
+
22
+ # Custom configuration
23
+ client = MregClient(
24
+ url="https://mreg.example.com",
25
+ cache=CacheConfig(ttl=600, directory="/var/tmp/mreg-cache"),
26
+ )
27
+ ```
28
+
29
+ ## `CacheConfig` options
30
+
31
+ | Field | Type | Default | Description |
32
+ |---|---|---|---|
33
+ | `enable` | `bool` | `True` | Whether the cache is active. |
34
+ | `ttl` | `int` | `300` | Time-to-live for cached entries, in seconds. |
35
+ | `tag` | `str` | `"mreg-api"` | Tag used to namespace cache entries. |
36
+ | `timeout` | `int` | `60` | Open timeout for the underlying disk cache. |
37
+ | `directory` | `str | None` | `None` | Cache directory. `None` uses a system temp directory. |
38
+
39
+ ## Controlling the cache at runtime
40
+
41
+ ```python
42
+ client.enable_cache() # turn caching on
43
+ client.enable_cache(CacheConfig(ttl=60)) # reconfigure and turn on
44
+ client.disable_cache() # turn off (clears by default)
45
+ client.disable_cache(clear=False) # turn off, keep cached data
46
+ client.clear_cache() # drop all cached entries
47
+ ```
48
+
49
+ Use the [`caching()`][mreg_api.client.MregClient.caching] context manager to toggle
50
+ caching for a block:
51
+
52
+ ```python
53
+ with client.caching(enable=True):
54
+ client.host.list() # served from / stored in the cache
55
+ ```
56
+
57
+ ## Inspecting the cache
58
+
59
+ ```python
60
+ info = client.get_cache_info() # CacheInfo, or None if caching is disabled
61
+ if info:
62
+ print(info.items, info.hits, info.misses, info.size)
63
+ ```
@@ -0,0 +1,64 @@
1
+ ---
2
+ icon: lucide/settings
3
+ ---
4
+
5
+ # Client configuration
6
+
7
+ Everything starts with an [`MregClient`][mreg_api.client.MregClient]. Constructing one
8
+ sets up the HTTP session but does **not** authenticate or make any network requests — see
9
+ [Authentication](authentication.md) for that.
10
+
11
+ ```python
12
+ from mreg_api import MregClient
13
+
14
+ client = MregClient(
15
+ url="https://mreg.example.com",
16
+ domain="example.com",
17
+ )
18
+ ```
19
+
20
+ ## Constructor options
21
+
22
+ | Argument | Type | Default | Description |
23
+ |---|---|---|---|
24
+ | `url` | `str` | *required* | Base URL of the MREG server. All request paths are joined onto it. |
25
+ | `domain` | `str | None` | `None` | Default DNS domain used to expand bare hostnames into FQDNs. See [Domain handling](#domain-handling). |
26
+ | `user` | `str | None` | `None` | Informational username stored on the client. Does **not** authenticate. |
27
+ | `timeout` | `int | float | None` | `60` | Request timeout in seconds, passed to the underlying HTTP client. |
28
+ | `cache` | `CacheConfig | bool` | `False` | Enable GET-response caching. `True` uses defaults; pass a [`CacheConfig`][mreg_api.cache.CacheConfig] to customize. See [Caching](caching.md). |
29
+ | `follow_redirects` | `bool` | `False` | Whether the HTTP client follows redirects. |
30
+ | `page_size` | `int | None` | `None` | Default pagination page size sent as a query parameter on GET requests. |
31
+ | `history_size` | `int | None` | `100` | Maximum number of request/response records kept in `client.history`. |
32
+ | `event_log_size` | `int | None` | `100` | Maximum number of entries kept in the [event log](../reference/events.md). |
33
+ | `user_agent` | `str | None` | `None` | Custom `User-Agent` header. Defaults to `mreg-api-<version>`. |
34
+
35
+ ## Domain handling
36
+
37
+ When `domain` is set, bare hostnames are expanded to FQDNs automatically by resource
38
+ methods. You can also expand a name explicitly or override the domain temporarily:
39
+
40
+ ```python
41
+ client.fqdn("web") # -> "web.example.com"
42
+
43
+ with client.domain_override("other.example.com"):
44
+ client.fqdn("web") # -> "web.other.example.com"
45
+ ```
46
+
47
+ ## Timeout
48
+
49
+ `timeout` is also available as a settable property after construction:
50
+
51
+ ```python
52
+ client.timeout = 120
53
+ ```
54
+
55
+ ## Request history
56
+
57
+ Every request/response pair is recorded in a bounded deque, sized by `history_size`:
58
+
59
+ ```python
60
+ for record in client.get_client_history():
61
+ print(record.method, record.status, record.url)
62
+
63
+ client.clear_client_history()
64
+ ```
@@ -0,0 +1,52 @@
1
+ ---
2
+ icon: lucide/chart-no-axes-gantt
3
+ ---
4
+
5
+ # Event Log
6
+
7
+ The client records an event log of resolutions, mutations, and notices that happen in-between requests for complex queries and multi-step operations. Typically, such events are things like CNAME and PTR resolution that happen when resolving Host or host records.
8
+
9
+ !!! note
10
+
11
+ The event log system is a new feature and is still under development. The API may change in future releases. As of 0.3.0, it only records CNAME and PTR resolution events, but future releases will include more event types.
12
+
13
+ ## Accessing the event log
14
+
15
+ The event log is accessible via the `client.events` property, which returns an [`EventLog`][mreg_api.events.EventLog] instance. The size of the log is controlled by the `event_log_size` argument to [`MregClient`][mreg_api.client.MregClient].
16
+
17
+ ```python
18
+ client = MregClient(...)
19
+ events = client.events.get()
20
+ ```
21
+
22
+ ## Filtering by event kind
23
+
24
+ Each event is categorized by kind ([`EventKind`][mreg_api.events.EventKind]). You can filter the event log by kind using the `get` method with the `kind` argument:
25
+
26
+ ```python
27
+ from mreg_api.events import EventKind
28
+
29
+ client.events.get(kind=EventKind.RESOLUTION)
30
+ client.events.get(kind=EventKind.MUTATION)
31
+ client.events.get(kind=EventKind.NOTICE)
32
+ ```
33
+
34
+ ## Filtering by event level
35
+
36
+ Each event is also categorized by level ([`EventLevel`][mreg_api.events.EventLevel]). You can filter the event log by level using the `get` method with the `level` argument:
37
+
38
+ ```python
39
+ from mreg_api.events import EventLevel
40
+
41
+ client.events.get(level=EventLevel.DEBUG)
42
+ client.events.get(level=EventLevel.INFO)
43
+ client.events.get(level=EventLevel.WARNING)
44
+ client.events.get(level=EventLevel.ERROR)
45
+ client.events.get(level=EventLevel.CRITICAL)
46
+ ```
47
+
48
+ The `min_level` argument can be used to retrieve events at or above a certain severity level instead of exactly matching a level:
49
+
50
+ ```python
51
+ client.events.get(min_level=EventLevel.WARNING)
52
+ ```
@@ -0,0 +1,15 @@
1
+ ---
2
+ icon: lucide/timeline
3
+ ---
4
+
5
+ # Request/Response History
6
+
7
+ The client records a request/response history of each interaction with the server. The history is a bounded deque, sized by the `history_size` argument to [`MregClient`][mreg_api.client.MregClient]. You can access the history via the `client.history` property, which returns a list of [`RequestRecord`][mreg_api.client.RequestRecord] instances, which contain the request and response objects for each interaction, as well as shortcuts for the request method, URL, data and json payloads, as well as response status code.
8
+
9
+ ```python
10
+ client = MregClient(...)
11
+ for record in client.get_client_history():
12
+ print(record.request.method, record.request.url, record.status)
13
+ assert record.status == record.response.status_code
14
+ print("Request payload:", record.data or record.json)
15
+ ```