CKAN harvester extension for TM Forum APIs.
It harvests product offerings/specifications, enriches them with related service specifications, resolves owner organizations from TMF Party data, and creates/updates datasets in CKAN.
- CKAN: 2.11 (current target)
- Python: 3.10
- Requires
ckanext-harvest
Harvester type name:
tmforum
This is the value to use when creating a Harvest Source in CKAN.
gather_stage
- Reads launched product offerings from TMF Product Catalog (
/productOffering). - Creates harvest objects using product specification id as GUID.
fetch_stage
- Fetches product specification (
/productSpecification/{id}). - Fetches related service specifications from configured service catalog.
- Stores normalized content on harvest object.
import_stage
- Resolves owner party from
relatedPartyusing configuredowner_role. - Resolves/creates owner organization in CKAN.
- Builds CKAN dataset and resources.
- Creates or updates package through harvest base logic.
Configuration is read from the Harvest Source JSON config (source.config) for runtime behavior.
Expected keys:
party_url(required)- Base TMF Party endpoint.
service_catalog_url(required)- Base TMF Service Catalog endpoint.
owner_role(optional)- Default:
owner - Used to select owner party from
relatedParty.
- Default:
marketplace_url(optional)- If set, adds an extra resource access URL:
{marketplace_url}/search/{offer_id}.
- If set, adds an extra resource access URL:
edp_url(optional)- If set, adds an extra resource access URL pointing to EDP.
The harvest source URL (source.url) is used as TMF Product Catalog base.
{
"party_url": "https://tmf.example.com/party",
"service_catalog_url": "https://tmf.example.com/serviceCatalogManagement/v4",
"owner_role": "Seller",
"marketplace_url": "https://marketplace.example.com",
"edp_url": "https://edc.example.com"
}Per service specification, resources are created with:
name,descriptionaccess_url(TMF product offering URL)conforms_to(TM Forum URIs)
Known specCharacteristic mappings:
URL->download_urlFormat->formatMedia Type->mimetype
Other characteristics are mapped to flattened resource keys:
tmf_char_<normalized_name>- if multiple values:
tmf_char_<normalized_name>_1,..._2, etc.
Duplicate characteristic names are ignored after first occurrence.
Owner organization is resolved from party data using DID in this order:
externalReferencewhereexternalReferenceType == "idm_id"and name starts withdidpartyCharacteristicwherename == "did"- fallback to
party_id
Generated CKAN org name format:
vc-org-<sha256(did)[:16]>
git clone https://github.com/SEAMWARE/ckanext-tmforum.git
cd ckanext-tmforum
pip install -e .
pip install -r requirements.txtEnable plugin:
ckan.plugins = ... harvest tmforum ...
Examples:
docker compose exec ckan-dev bash -lc "ckan -c /srv/app/ckan.ini harvester sources" docker compose exec ckan-dev bash -lc "ckan -c /srv/app/ckan.ini harvester jobs" docker compose exec ckan-dev bash -lc "ckan -c /srv/app/ckan.ini harvester run-test <source_id_or_name>" docker compose exec ckan-dev bash -lc "ckan -c /srv/app/ckan.ini harvester gather-consumer" docker compose exec ckan-dev bash -lc "ckan -c /srv/app/ckan.ini harvester fetch-consumer"
Run all tests:
pytest --ckan-ini=test.iniRun unit tests only:
pytest --ckan-ini=test.ini ckanext/tmforum/tests/unit-
Update version in
pyproject.toml -
Build and validate:
python -m build && twine check dist/* -
Upload:
twine upload dist/* -
Commit and tag:
git commit -a -m "Release x.y.z"
git push
git tag x.y.z
git push --tags