mreg-api 0.2.2__tar.gz → 0.3.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.
- mreg_api-0.3.0/.github/workflows/test.yml +52 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/.gitignore +5 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/CHANGELOG.md +23 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/PKG-INFO +2 -2
- mreg_api-0.3.0/TESTING.md +136 -0
- mreg_api-0.3.0/ci/Dockerfile +15 -0
- mreg_api-0.3.0/ci/docker-compose.yml +39 -0
- mreg_api-0.3.0/ci/run_tests.sh +94 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/_version.py +3 -3
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/cache.py +27 -2
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/client.py +228 -171
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/endpoints.py +3 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/events.py +49 -5
- mreg_api-0.3.0/mreg_api/managers.py +4617 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/models/__init__.py +2 -0
- mreg_api-0.3.0/mreg_api/models/abstracts.py +33 -0
- mreg_api-0.3.0/mreg_api/models/fields.py +198 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/models/history.py +0 -30
- mreg_api-0.3.0/mreg_api/models/models.py +1293 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/types.py +1 -11
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api.egg-info/PKG-INFO +2 -2
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api.egg-info/SOURCES.txt +25 -1
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api.egg-info/requires.txt +1 -1
- mreg_api-0.3.0/mreg_api.egg-info/scm_file_list.json +65 -0
- mreg_api-0.3.0/mreg_api.egg-info/scm_version.json +8 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/pyproject.toml +60 -23
- mreg_api-0.3.0/tests/__init__.py +0 -0
- mreg_api-0.3.0/tests/conftest.py +12 -0
- mreg_api-0.3.0/tests/integration/__init__.py +0 -0
- mreg_api-0.3.0/tests/integration/conftest.py +226 -0
- mreg_api-0.3.0/tests/integration/test_atoms.py +316 -0
- mreg_api-0.3.0/tests/integration/test_cname.py +175 -0
- mreg_api-0.3.0/tests/integration/test_dhcp.py +68 -0
- mreg_api-0.3.0/tests/integration/test_host_records.py +773 -0
- mreg_api-0.3.0/tests/integration/test_hostgroups.py +284 -0
- mreg_api-0.3.0/tests/integration/test_hosts.py +234 -0
- mreg_api-0.3.0/tests/integration/test_ip.py +158 -0
- mreg_api-0.3.0/tests/integration/test_labels.py +192 -0
- mreg_api-0.3.0/tests/integration/test_meta.py +49 -0
- mreg_api-0.3.0/tests/integration/test_network_policy.py +377 -0
- mreg_api-0.3.0/tests/integration/test_networks.py +324 -0
- mreg_api-0.3.0/tests/integration/test_permissions.py +202 -0
- mreg_api-0.3.0/tests/integration/test_roles.py +323 -0
- mreg_api-0.3.0/tests/integration/test_zones.py +242 -0
- mreg_api-0.3.0/tests/models/test_fields.py +457 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/models/test_models.py +20 -2
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/test_client.py +141 -196
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/test_events.py +5 -9
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/test_exceptions.py +1 -5
- mreg_api-0.3.0/tests/test_managers.py +131 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/uv.lock +79 -8
- mreg_api-0.2.2/.github/workflows/test.yml +0 -30
- mreg_api-0.2.2/mreg_api/models/abstracts.py +0 -558
- mreg_api-0.2.2/mreg_api/models/fields.py +0 -198
- mreg_api-0.2.2/mreg_api/models/models.py +0 -4435
- mreg_api-0.2.2/tests/conftest.py +0 -39
- mreg_api-0.2.2/tests/models/test_fields.py +0 -275
- mreg_api-0.2.2/tests/models/test_history.py +0 -40
- /mreg_api-0.2.2/mreg_api/py.typed → /mreg_api-0.3.0/.claude/CLAUDE.md +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/.github/workflows/publish.yml +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/.markdownlint.json +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/.pre-commit-config.yaml +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/LICENSE +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/NOTES.md +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/README.md +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/__about__.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/__init__.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/exceptions.py +0 -0
- /mreg_api-0.2.2/tests/__init__.py → /mreg_api-0.3.0/mreg_api/py.typed +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/utilities/__init__.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/utilities/fs.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api/utilities/shared.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api.egg-info/dependency_links.txt +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/mreg_api.egg-info/top_level.txt +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/setup.cfg +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/models/__init__.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/test_cache.py +0 -0
- {mreg_api-0.2.2 → mreg_api-0.3.0}/tests/test_types.py +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
on:
|
|
2
|
+
push:
|
|
3
|
+
pull_request:
|
|
4
|
+
|
|
5
|
+
env:
|
|
6
|
+
UV_FROZEN: 1
|
|
7
|
+
|
|
8
|
+
name: Tests
|
|
9
|
+
jobs:
|
|
10
|
+
unit:
|
|
11
|
+
name: Unit tests
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version:
|
|
17
|
+
- "3.11"
|
|
18
|
+
- "3.12"
|
|
19
|
+
- "3.13"
|
|
20
|
+
- "3.14"
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v2
|
|
25
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
26
|
+
run: uv python install ${{ matrix.python-version }}
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync
|
|
29
|
+
- name: Run unit tests
|
|
30
|
+
run: bash ci/run_tests.sh --unit-only --no-cov
|
|
31
|
+
|
|
32
|
+
integration:
|
|
33
|
+
name: Integration tests
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
strategy:
|
|
36
|
+
fail-fast: false
|
|
37
|
+
matrix:
|
|
38
|
+
python-version:
|
|
39
|
+
- "3.11"
|
|
40
|
+
- "3.12"
|
|
41
|
+
- "3.13"
|
|
42
|
+
- "3.14"
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- name: Install uv
|
|
46
|
+
uses: astral-sh/setup-uv@v2
|
|
47
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
48
|
+
run: uv python install ${{ matrix.python-version }}
|
|
49
|
+
- name: Install dependencies
|
|
50
|
+
run: uv sync
|
|
51
|
+
- name: Run integration tests
|
|
52
|
+
run: bash ci/run_tests.sh --integration-only --no-cov
|
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
<!-- ## Unreleased -->
|
|
9
9
|
|
|
10
|
+
## [0.3.0](https://github.com/unioslo/mreg-api/releases/tag/0.3.0) - 2026-08-12
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `Host.get_community_associations(name: str)` method to retrieve all ipaddress->community associations for the host with the given community name.
|
|
15
|
+
- `Network.get_communities(name: str)` method to retrieve all communities with the given name.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **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
|
+
- `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
|
+
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- **BREAKING**: `MregClient.reset_instance` removed because the singleton pattern has been removed.
|
|
26
|
+
|
|
27
|
+
## [0.2.3](https://github.com/unioslo/mreg-api/releases/tag/0.2.3) - 2026-05-21
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Fixed `NAPTR` fields missing defaults after removal of nullability.
|
|
32
|
+
|
|
10
33
|
## [0.2.2](https://github.com/unioslo/mreg-api/releases/tag/0.2.2) - 2026-04-23
|
|
11
34
|
|
|
12
35
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mreg-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.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>
|
|
@@ -692,7 +692,7 @@ Requires-Python: >=3.11
|
|
|
692
692
|
Description-Content-Type: text/markdown
|
|
693
693
|
License-File: LICENSE
|
|
694
694
|
Requires-Dist: httpx[socks]>=0.28.1
|
|
695
|
-
Requires-Dist:
|
|
695
|
+
Requires-Dist: typing-extensions>=4.16.0
|
|
696
696
|
Requires-Dist: pydantic>=2.12
|
|
697
697
|
Requires-Dist: pydantic-extra-types>=2.1.0
|
|
698
698
|
Requires-Dist: diskcache>=5.6.3
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
mreg-api has two types of tests:
|
|
4
|
+
|
|
5
|
+
- **Unit tests** — Unit testing of functions and methods used by the package. No interaction with a live mreg server is required.
|
|
6
|
+
- **Integration tests** — Run against a live (containerized) mreg server. Skipped automatically when no server URL is configured.
|
|
7
|
+
|
|
8
|
+
## Unit tests
|
|
9
|
+
|
|
10
|
+
Unit tests use `pytest-httpserver` to mock MREG server responses for any tests that require HTTP interactions. No external services required.
|
|
11
|
+
|
|
12
|
+
Bare `pytest` invocations ignore integration tests (skipped automatically when no server URL is configured):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
uv run pytest
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
In case some configuration defines `MREG_URL`, unit tests can still be run exclusively by ignoring the integration tests via markers:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv run pytest -m "not integration"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Integration tests
|
|
25
|
+
|
|
26
|
+
Integration tests run against a live mreg server. They are **skipped automatically** when no server URL is configured, so `uv run pytest` never fails due to a missing server.
|
|
27
|
+
|
|
28
|
+
### Prerequisites
|
|
29
|
+
|
|
30
|
+
A running mreg instance (and PostgreSQL). The fastest way is the containerized setup:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bash ci/run_tests.sh
|
|
34
|
+
|
|
35
|
+
# If port 8000 is already in use (e.g., a local mreg dev server):
|
|
36
|
+
MREG_PORT=8081 bash ci/run_tests.sh
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This starts containers, creates a superuser, then runs both unit and integration tests with combined coverage output in `htmlcov/`.
|
|
40
|
+
|
|
41
|
+
Flags:
|
|
42
|
+
|
|
43
|
+
| Flag | Effect |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `--unit-only` | Skip integration tests (no containers started) |
|
|
46
|
+
| `--integration-only` | Skip unit tests |
|
|
47
|
+
| `--no-cov` | Disable coverage. Used in CI |
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Fast run without coverage
|
|
51
|
+
bash ci/run_tests.sh --no-cov
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Running manually against a local server
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Minimal — username/password default to "test"
|
|
58
|
+
MREG_URL=http://127.0.0.1:8000 uv run pytest tests/integration/
|
|
59
|
+
|
|
60
|
+
# All options explicit
|
|
61
|
+
MREG_URL=http://127.0.0.1:8000 \
|
|
62
|
+
MREG_USERNAME=myuser \
|
|
63
|
+
MREG_PASSWORD=secret \
|
|
64
|
+
MREG_DOMAIN=example.com \
|
|
65
|
+
MREG_CACHE=0 \
|
|
66
|
+
MREG_TEST_NETWORK=10.0.0.0/8 \
|
|
67
|
+
uv run pytest tests/integration/ -v
|
|
68
|
+
|
|
69
|
+
# Via CLI flags instead of env vars
|
|
70
|
+
uv run pytest tests/integration/ \
|
|
71
|
+
--mreg-url http://127.0.0.1:8000 \
|
|
72
|
+
--mreg-username myuser \
|
|
73
|
+
--mreg-password secret
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Configuration
|
|
77
|
+
|
|
78
|
+
| Env var | CLI flag | Default | Description |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `MREG_URL` | `--mreg-url` | *(none — required to activate integration tests)* | mreg server base URL |
|
|
81
|
+
| `MREG_USERNAME` | `--mreg-username` | `test` | Login username |
|
|
82
|
+
| `MREG_PASSWORD` | `--mreg-password` | `test` | Login password |
|
|
83
|
+
| `MREG_DOMAIN` | `--mreg-domain` | `example.com` | Default domain for the client. Controls the main zone used in integration tests |
|
|
84
|
+
| `MREG_CACHE` | `--mreg-cache` | `false` | Enable mreg client cache (`1`/`true`/`yes` = on) |
|
|
85
|
+
| `MREG_TEST_NETWORK` | `--test-network` | `10.0.0.0/8` | Network CIDR created as shared test network |
|
|
86
|
+
| `MREG_TEST_IP` | `--test-ip` | `10.0.0.1` | IP address used in IP-related tests |
|
|
87
|
+
|
|
88
|
+
CLI flags take precedence over env vars.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Subset runs
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Read-only tests only (safe against staging/production)
|
|
95
|
+
uv run pytest tests/integration/ -m readonly
|
|
96
|
+
|
|
97
|
+
# Single resource type
|
|
98
|
+
uv run pytest tests/integration/test_labels.py
|
|
99
|
+
|
|
100
|
+
# Specific test
|
|
101
|
+
uv run pytest tests/integration/test_labels.py::test_delete_by_name
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Coverage
|
|
105
|
+
|
|
106
|
+
### Unit tests only
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
uv run pytest tests/ --ignore=tests/integration \
|
|
110
|
+
--cov=mreg_api --cov-report=term-missing
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Combined unit + integration
|
|
114
|
+
|
|
115
|
+
Run `ci/run_tests.sh` (uses `--cov-append` to merge both passes), or manually:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Pass 1: unit tests — write .coverage
|
|
119
|
+
uv run pytest tests/ --ignore=tests/integration \
|
|
120
|
+
--cov=mreg_api --cov-report=
|
|
121
|
+
|
|
122
|
+
# Pass 2: integration tests — append to .coverage
|
|
123
|
+
MREG_URL=http://127.0.0.1:8000 MREG_USERNAME=test MREG_PASSWORD=test \
|
|
124
|
+
uv run pytest tests/integration/ \
|
|
125
|
+
--cov=mreg_api --cov-append --cov-report=html --cov-report=term
|
|
126
|
+
|
|
127
|
+
# Open report
|
|
128
|
+
open htmlcov/index.html
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Markers
|
|
132
|
+
|
|
133
|
+
| Marker | Meaning |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `integration` | Requires live mreg server — skipped without `MREG_URL` |
|
|
136
|
+
| `readonly` | Test only reads data, safe against staging/production servers |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM ubuntu:latest
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
4
|
+
curl \
|
|
5
|
+
git \
|
|
6
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
7
|
+
|
|
8
|
+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
9
|
+
ENV PATH="/root/.local/bin:$PATH"
|
|
10
|
+
|
|
11
|
+
RUN uv python install 3.12
|
|
12
|
+
|
|
13
|
+
WORKDIR /build
|
|
14
|
+
COPY . .
|
|
15
|
+
RUN uv sync -q
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
services:
|
|
2
|
+
postgres:
|
|
3
|
+
image: postgres
|
|
4
|
+
environment:
|
|
5
|
+
POSTGRES_USER: mreg
|
|
6
|
+
POSTGRES_DB: mreg
|
|
7
|
+
POSTGRES_PASSWORD: mreg
|
|
8
|
+
healthcheck:
|
|
9
|
+
test: ["CMD", "pg_isready", "--username=mreg"]
|
|
10
|
+
interval: 5s
|
|
11
|
+
timeout: 5s
|
|
12
|
+
retries: 10
|
|
13
|
+
|
|
14
|
+
mreg:
|
|
15
|
+
image: ${MREG_IMAGE:-ghcr.io/unioslo/mreg:master}
|
|
16
|
+
container_name: mreg
|
|
17
|
+
depends_on:
|
|
18
|
+
postgres:
|
|
19
|
+
condition: service_healthy
|
|
20
|
+
ports:
|
|
21
|
+
- "${MREG_PORT:-8000}:8000"
|
|
22
|
+
environment:
|
|
23
|
+
MREG_DB_HOST: postgres
|
|
24
|
+
MREG_DB_NAME: mreg
|
|
25
|
+
MREG_DB_USER: mreg
|
|
26
|
+
MREG_DB_PASSWORD: mreg
|
|
27
|
+
MREG_MAP_GLOBAL_COMMUNITY_NAMES: "1"
|
|
28
|
+
CI: "yes"
|
|
29
|
+
healthcheck:
|
|
30
|
+
test: ["CMD", "test", "-f", "/var/run/gunicorn.pid"]
|
|
31
|
+
interval: 5s
|
|
32
|
+
timeout: 5s
|
|
33
|
+
retries: 20
|
|
34
|
+
|
|
35
|
+
wait:
|
|
36
|
+
image: hello-world
|
|
37
|
+
depends_on:
|
|
38
|
+
mreg:
|
|
39
|
+
condition: service_healthy
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
6
|
+
|
|
7
|
+
RUN_UNIT=true
|
|
8
|
+
RUN_INTEGRATION=true
|
|
9
|
+
RUN_COVERAGE=true
|
|
10
|
+
MREG_IMAGE="${MREG_IMAGE:-ghcr.io/unioslo/mreg:master}"
|
|
11
|
+
# Host port the mreg container is exposed on. Override if 8000 is already in use.
|
|
12
|
+
MREG_PORT="${MREG_PORT:-8000}"
|
|
13
|
+
MREG_URL="${MREG_URL:-http://127.0.0.1:${MREG_PORT}}"
|
|
14
|
+
MREG_USERNAME="${MREG_USERNAME:-test}"
|
|
15
|
+
MREG_PASSWORD="${MREG_PASSWORD:-test}"
|
|
16
|
+
MREG_CACHE="${MREG_CACHE:-0}"
|
|
17
|
+
|
|
18
|
+
while [[ $# -gt 0 ]]; do
|
|
19
|
+
case $1 in
|
|
20
|
+
--unit-only) RUN_INTEGRATION=false; shift ;;
|
|
21
|
+
--integration-only) RUN_UNIT=false; shift ;;
|
|
22
|
+
--no-cov) RUN_COVERAGE=false; shift ;;
|
|
23
|
+
*) shift ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
if command -v podman &>/dev/null && ! command -v docker &>/dev/null; then
|
|
28
|
+
DOCKER=podman
|
|
29
|
+
else
|
|
30
|
+
DOCKER=docker
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [[ "$RUN_INTEGRATION" == "true" ]]; then
|
|
34
|
+
# Check if port is already in use before starting containers
|
|
35
|
+
if lsof -i ":${MREG_PORT}" 2>/dev/null | grep -q LISTEN; then
|
|
36
|
+
echo "ERROR: Port ${MREG_PORT} is already in use." >&2
|
|
37
|
+
echo "Set MREG_PORT to a free port: MREG_PORT=8081 bash ci/run_tests.sh" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
cleanup() {
|
|
42
|
+
cd "$SCRIPT_DIR"
|
|
43
|
+
$DOCKER compose down --remove-orphans 2>/dev/null || true
|
|
44
|
+
}
|
|
45
|
+
trap cleanup EXIT
|
|
46
|
+
|
|
47
|
+
cd "$SCRIPT_DIR"
|
|
48
|
+
|
|
49
|
+
echo "Starting mreg and postgres on port ${MREG_PORT}..."
|
|
50
|
+
MREG_IMAGE="$MREG_IMAGE" MREG_PORT="$MREG_PORT" $DOCKER compose up -d
|
|
51
|
+
|
|
52
|
+
echo "Creating superuser..."
|
|
53
|
+
$DOCKER exec mreg uv run /app/manage.py create_mreg_superuser \
|
|
54
|
+
--username "$MREG_USERNAME" --password "$MREG_PASSWORD" 2>/dev/null \
|
|
55
|
+
|| $DOCKER exec mreg /app/manage.py create_mreg_superuser \
|
|
56
|
+
--username "$MREG_USERNAME" --password "$MREG_PASSWORD"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
cd "$REPO_ROOT"
|
|
62
|
+
|
|
63
|
+
UNIT_EXIT=0
|
|
64
|
+
INTEGRATION_EXIT=0
|
|
65
|
+
|
|
66
|
+
if [[ "$RUN_UNIT" == "true" ]]; then
|
|
67
|
+
echo "Running unit tests..."
|
|
68
|
+
UNIT_ARGS=(tests/ --ignore=tests/integration -v)
|
|
69
|
+
if [[ "$RUN_COVERAGE" == "true" ]]; then
|
|
70
|
+
UNIT_ARGS+=(--cov=mreg_api --cov-report=)
|
|
71
|
+
else
|
|
72
|
+
UNIT_ARGS+=(--no-cov)
|
|
73
|
+
fi
|
|
74
|
+
uv run pytest "${UNIT_ARGS[@]}" || UNIT_EXIT=$?
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if [[ "$RUN_INTEGRATION" == "true" ]]; then
|
|
78
|
+
echo "Running integration tests..."
|
|
79
|
+
INTEGRATION_ARGS=(tests/integration/ -v)
|
|
80
|
+
if [[ "$RUN_COVERAGE" == "true" ]]; then
|
|
81
|
+
INTEGRATION_ARGS+=(--cov=mreg_api --cov-append --cov-report=html --cov-report=term)
|
|
82
|
+
else
|
|
83
|
+
INTEGRATION_ARGS+=(--no-cov)
|
|
84
|
+
fi
|
|
85
|
+
MREG_URL="$MREG_URL" \
|
|
86
|
+
MREG_USERNAME="$MREG_USERNAME" \
|
|
87
|
+
MREG_PASSWORD="$MREG_PASSWORD" \
|
|
88
|
+
uv run pytest "${INTEGRATION_ARGS[@]}" || INTEGRATION_EXIT=$?
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
if [[ $UNIT_EXIT -ne 0 || $INTEGRATION_EXIT -ne 0 ]]; then
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
exit 0
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gd440dfea6'
|
|
@@ -17,6 +17,15 @@ from pydantic import field_serializer
|
|
|
17
17
|
from mreg_api.exceptions import CacheError
|
|
18
18
|
from mreg_api.exceptions import CacheMiss
|
|
19
19
|
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CacheConfig",
|
|
22
|
+
"MregApiCache",
|
|
23
|
+
"CacheInfo",
|
|
24
|
+
"CacheError",
|
|
25
|
+
"CacheMiss",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
20
29
|
logger = logging.getLogger(__name__)
|
|
21
30
|
|
|
22
31
|
|
|
@@ -77,6 +86,10 @@ class CacheConfig(BaseModel):
|
|
|
77
86
|
directory: str | None = None
|
|
78
87
|
|
|
79
88
|
|
|
89
|
+
# NOTE: this class used to make more sense when we had a protocol type for
|
|
90
|
+
# the backend class. Now that the backend class is explicitly `diskcache.Cache`,
|
|
91
|
+
# this class is mostly a wrapper around the cache instance and config.
|
|
92
|
+
# TODO: support other cache types: in-memory, etc.
|
|
80
93
|
@final
|
|
81
94
|
class MregApiCache(Generic[T]):
|
|
82
95
|
"""Wrapper around the mreg-api cache.
|
|
@@ -93,8 +106,8 @@ class MregApiCache(Generic[T]):
|
|
|
93
106
|
|
|
94
107
|
Warning:
|
|
95
108
|
NEVER use `if self._cache` checks! diskcache.Cache implements `__bool__`
|
|
96
|
-
to
|
|
97
|
-
`if self._cache is None` instead.
|
|
109
|
+
to report whether the cache is NON-EMPTY, not whether it EXISTS.
|
|
110
|
+
Always use `if self._cache is None` instead in this class.
|
|
98
111
|
"""
|
|
99
112
|
|
|
100
113
|
def __init__(self, cache: Cache | None, config: CacheConfig) -> None:
|
|
@@ -141,6 +154,18 @@ class MregApiCache(Generic[T]):
|
|
|
141
154
|
"""Disable the cache."""
|
|
142
155
|
self.config.enable = False
|
|
143
156
|
|
|
157
|
+
def close(self) -> None:
|
|
158
|
+
"""Close the cache and release resources."""
|
|
159
|
+
if self._cache is not None:
|
|
160
|
+
try:
|
|
161
|
+
self._cache.close()
|
|
162
|
+
except Exception as e:
|
|
163
|
+
logger.warning("Failed to close cache: %s", e)
|
|
164
|
+
finally:
|
|
165
|
+
# Unbind the object reference, allowing it to be garbage collected
|
|
166
|
+
# regardless of whether close() succeeded or not.
|
|
167
|
+
self._cache = None
|
|
168
|
+
|
|
144
169
|
def get_info(self) -> CacheInfo | None:
|
|
145
170
|
"""Get information about the cache.
|
|
146
171
|
|