Skip to main content

Runtime conformance checker for TMForum Open API implementations — ESLint for TMF APIs

Project description

tmf-lint

CI PyPI Python License

Runtime conformance checker for TMForum Open API implementations.

tmf-lint points at a running TMF API server and validates its behaviour against the TMForum Open API v4.0.0 spec. Think ESLint for TMF APIs — not a Swagger/OAS linter (TMFValidator does that), but a live HTTP behaviour validator.

Part of the TMF DevKit open-source toolchain.


Quick start

pip install tmf-lint

# Option A — use tmf-mock as the target (recommended for a clean baseline)
pip install tmf-mock
tmf-mock start --apis 638,639,641

# Option B — point at your own server
# (read the "Target server requirements" section below first)

# Run all conformance checks
tmf-lint check --url http://localhost:8000 --apis 638,639,641

What it checks

39 rules across 5 categories for TMF638, TMF639, and TMF641.

Category What is validated
http POST→201 with Location header, GET list→200 with X-Total-Count, GET unknown id→404, DELETE→204
mandatory-fields id, href, @type, @baseType present on every response; href is an absolute URL
lifecycle Valid state transitions accepted (200), illegal transitions rejected (422), terminal states locked, same-state PATCH is a no-op (200)
referential DELETE a resource referenced by a service→409, POST with a non-existent reference→422
pagination limit param respected, X-Total-Count accurate (verified by fetching limit=total), offset beyond total returns empty array not an error

CLI reference

# Check all rules against all three supported APIs
tmf-lint check --url http://myserver:8080 --apis 638,639,641

# Check only specific rule categories
tmf-lint check --url http://myserver:8080 --apis 638 --rules http,lifecycle

# JSON output for CI/CD pipelines
tmf-lint check --url http://myserver:8080 --format json

# List all available rules
tmf-lint rules

# Filter rule list by API
tmf-lint rules --apis 639

# Show version
tmf-lint --version

Exit code 0 = all checks passed. Exit code 1 = one or more failures.


Target server requirements

tmf-lint creates, modifies, and deletes real data on the server it checks. It sends minimal spec-compliant payloads (only fields defined in the TMF v4.0.0 schema).

Always point tmf-lint at a test or mock instance — never at production.

If your server enforces fields beyond the TMF spec

Some implementations require fields that the spec marks as optional — for example relatedParty, resourceSpecification, a specific @type subclass, or a valid serviceSpecification reference. If a setup POST is rejected because of a missing field, the rule that depends on it will skip gracefully (you will see ⏭ in the output) rather than crash. You will not get a false failure, but you will not get a pass signal either.

In that case the recommended approach for v0.1 is to run tmf-lint against tmf-mock first to establish a clean baseline, then use the results to understand which rules your server needs to satisfy. A --fixtures option (v0.2) will allow you to supply custom POST payloads for your specific implementation.

URL base path

tmf-lint expects the standard TMForum base paths:

API Path
TMF638 /tmf-api/serviceInventoryManagement/v4/service
TMF639 /tmf-api/resourceInventoryManagement/v4/resource
TMF641 /tmf-api/serviceOrdering/v4/serviceOrder

Docker

# Run against a local server
docker run --rm --network host mchavan23/tmf-lint \
  check --url http://localhost:8000 --apis 638,639,641

# JSON output
docker run --rm --network host mchavan23/tmf-lint \
  check --url http://localhost:8000 --format json

CI/CD integration

# GitHub Actions example
- name: TMF API conformance check
  run: |
    pip install tmf-lint
    tmf-lint check --url http://localhost:8000 --apis 638,639,641 --format json \
      | tee tmf-lint-report.json
    # exit code 1 if any rule fails — fails the build automatically

Programmatic use

from tmf_lint.runner import run

report = run(base_url="http://localhost:8000", apis=[638, 639, 641])
print(f"Passed: {report.n_passed}  Failed: {report.n_failed}  Skipped: {report.n_skipped}")

for result in report.results:
    if not result.passed and not result.skipped:
        print(f"  FAIL [{result.rule_id}] {result.description}")
        print(f"       {result.message}")

Adding a new rule

The rule engine auto-discovers subclasses — no registration call is needed.

  1. Create tmf_lint/rules/tmf{N}/r_mycheck.py
  2. Subclass BaseRule and set four class attributes
  3. Implement async def check(self, client, ctx) -> RuleResult
from tmf_lint.rules.base import BaseRule, CATEGORY_HTTP
from tmf_lint.client import LintClient
from tmf_lint.context import LintContext
from tmf_lint.result import RuleResult

class TMF639MyNewRule(BaseRule):
    rule_id    = "TMF639-HTTP-005"
    api        = 639
    category   = CATEGORY_HTTP
    description = "GET /resource supports ?fields= projection"

    async def check(self, client: LintClient, ctx: LintContext) -> RuleResult:
        try:
            resp = await client.get("/tmf-api/resourceInventoryManagement/v4/resource",
                                    params={"fields": "id,name"})
        except Exception as exc:
            return self.fail(str(exc))

        if resp.status_code != 200:
            return self.fail(f"Expected 200, got {resp.status_code}")
        return self.ok()

See tmf_lint/rules/tmf639/r_http.py for a complete worked example.


Development

git clone https://github.com/tmf-devkit/tmf-lint
cd tmf-lint

# Windows
python -m venv .venv && .venv\Scripts\activate
# macOS / Linux
python -m venv .venv && source .venv/bin/activate

pip install -e ".[dev]"
pytest                  # all tests, no live server needed
ruff check tmf_lint     # lint

Related projects

Project Purpose
tmf-mock Smart TMF mock server — the recommended test target for tmf-lint
TMFValidator OAS/Swagger schema linter — validates the API definition, not runtime behaviour

Roadmap

Version Planned additions
v0.2 --fixtures for custom POST payloads, TMF688 notification checks
v0.3 TMF633 Service Catalog, TMF634 Resource Catalog

License

Apache 2.0 © Manoj Chavan

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tmf_lint-0.1.0.tar.gz (29.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tmf_lint-0.1.0-py3-none-any.whl (37.8 kB view details)

Uploaded Python 3

File details

Details for the file tmf_lint-0.1.0.tar.gz.

File metadata

  • Download URL: tmf_lint-0.1.0.tar.gz
  • Upload date:
  • Size: 29.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for tmf_lint-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e3482553bd35d3dc6fdc24b7c7c38ceee6dbdddc84b6c9e40512c9081c99dea6
MD5 d541b1cceaf3065d10b48e0f17d0ca3a
BLAKE2b-256 299a036ad539a231264fd0c6627e47052b741afb1796622ad85cf0f76aadad9a

See more details on using hashes here.

File details

Details for the file tmf_lint-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tmf_lint-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for tmf_lint-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1f705ca980e684c416be67984d7480d5d06ef6e367a523ef32dc7d054bd3a068
MD5 da5f1a2d2e9ca09f60d5bc276a5d61f5
BLAKE2b-256 067a28b6291afe088ab004d5cc7fcaa73e93bd0bc35cd8043193a47d12499447

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page