mule-discovery 1.0.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.
- mule_discovery-1.0.0/.claude/settings.local.json +18 -0
- mule_discovery-1.0.0/.github/workflows/tests.yml +27 -0
- mule_discovery-1.0.0/.gitignore +35 -0
- mule_discovery-1.0.0/Makefile +52 -0
- mule_discovery-1.0.0/PKG-INFO +236 -0
- mule_discovery-1.0.0/README.md +217 -0
- mule_discovery-1.0.0/pyproject.toml +53 -0
- mule_discovery-1.0.0/src/mule_discovery/__init__.py +288 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/__init__.py +1 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/classification.py +67 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/complexity.py +98 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/dependencies.py +291 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/patterns.py +27 -0
- mule_discovery-1.0.0/src/mule_discovery/analysis/scoring.py +202 -0
- mule_discovery-1.0.0/src/mule_discovery/anypoint/__init__.py +1 -0
- mule_discovery-1.0.0/src/mule_discovery/anypoint/exchange.py +21 -0
- mule_discovery-1.0.0/src/mule_discovery/anypoint/policies.py +14 -0
- mule_discovery-1.0.0/src/mule_discovery/cli/__init__.py +1 -0
- mule_discovery-1.0.0/src/mule_discovery/cli/discover.py +101 -0
- mule_discovery-1.0.0/src/mule_discovery/cli/download_policies.py +46 -0
- mule_discovery-1.0.0/src/mule_discovery/cli/scan_policies.py +51 -0
- mule_discovery-1.0.0/src/mule_discovery/constants.py +183 -0
- mule_discovery-1.0.0/src/mule_discovery/models/__init__.py +64 -0
- mule_discovery-1.0.0/src/mule_discovery/models/connectors.py +22 -0
- mule_discovery-1.0.0/src/mule_discovery/models/dataweave.py +21 -0
- mule_discovery-1.0.0/src/mule_discovery/models/dependencies.py +33 -0
- mule_discovery-1.0.0/src/mule_discovery/models/flows.py +216 -0
- mule_discovery-1.0.0/src/mule_discovery/models/listeners.py +28 -0
- mule_discovery-1.0.0/src/mule_discovery/models/result.py +53 -0
- mule_discovery-1.0.0/src/mule_discovery/models/schemas.py +12 -0
- mule_discovery-1.0.0/src/mule_discovery/models/scoring.py +40 -0
- mule_discovery-1.0.0/src/mule_discovery/output/__init__.py +1 -0
- mule_discovery-1.0.0/src/mule_discovery/output/json_output.py +12 -0
- mule_discovery-1.0.0/src/mule_discovery/output/text_output.py +35 -0
- mule_discovery-1.0.0/src/mule_discovery/output/yaml_output.py +26 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/__init__.py +1 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/aws.py +124 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/dataweave.py +107 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/file_discovery.py +165 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/http_auth.py +158 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/mule_xml.py +810 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/openapi.py +93 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/pom.py +185 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/soap.py +126 -0
- mule_discovery-1.0.0/src/mule_discovery/parsers/wsdl.py +58 -0
- mule_discovery-1.0.0/src/mule_discovery/xml_helpers.py +213 -0
- mule_discovery-1.0.0/tests/__init__.py +0 -0
- mule_discovery-1.0.0/tests/conftest.py +106 -0
- mule_discovery-1.0.0/tests/fixtures/batch_app/pom.xml +6 -0
- mule_discovery-1.0.0/tests/fixtures/batch_app/src/main/mule/batch-job.xml +27 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/pom.xml +31 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/src/main/mule/api.xml +48 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/src/main/mule/globals.xml +10 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/src/main/resources/dwl/complex.dwl +11 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/src/main/resources/dwl/simple.dwl +7 -0
- mule_discovery-1.0.0/tests/fixtures/complex_app/src/main/resources/dwl/trivial.dwl +4 -0
- mule_discovery-1.0.0/tests/fixtures/event_driven_app/pom.xml +13 -0
- mule_discovery-1.0.0/tests/fixtures/event_driven_app/src/main/mule/event-flows.xml +15 -0
- mule_discovery-1.0.0/tests/fixtures/mule3_app/pom.xml +9 -0
- mule_discovery-1.0.0/tests/fixtures/mule3_app/src/main/app/mule-config.xml +9 -0
- mule_discovery-1.0.0/tests/fixtures/simple_api_app/pom.xml +22 -0
- mule_discovery-1.0.0/tests/fixtures/simple_api_app/src/main/mule/api.xml +38 -0
- mule_discovery-1.0.0/tests/fixtures/simple_api_app/src/main/mule/globals.xml +15 -0
- mule_discovery-1.0.0/tests/fixtures/soap_app/pom.xml +13 -0
- mule_discovery-1.0.0/tests/fixtures/soap_app/src/main/mule/soap-flows.xml +16 -0
- mule_discovery-1.0.0/tests/fixtures/soap_app/src/main/resources/wsdl/service.wsdl +26 -0
- mule_discovery-1.0.0/tests/test_analysis/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_analysis/test_classification.py +75 -0
- mule_discovery-1.0.0/tests/test_analysis/test_complexity.py +145 -0
- mule_discovery-1.0.0/tests/test_analysis/test_dependencies.py +398 -0
- mule_discovery-1.0.0/tests/test_analysis/test_patterns.py +39 -0
- mule_discovery-1.0.0/tests/test_analysis/test_scoring.py +410 -0
- mule_discovery-1.0.0/tests/test_anypoint/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_anypoint/test_exchange.py +21 -0
- mule_discovery-1.0.0/tests/test_anypoint/test_policies.py +20 -0
- mule_discovery-1.0.0/tests/test_cli/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_cli/test_discover_cli.py +148 -0
- mule_discovery-1.0.0/tests/test_cli/test_download_policies_cli.py +76 -0
- mule_discovery-1.0.0/tests/test_cli/test_scan_policies_cli.py +113 -0
- mule_discovery-1.0.0/tests/test_constants.py +52 -0
- mule_discovery-1.0.0/tests/test_discover_mule_app.py +274 -0
- mule_discovery-1.0.0/tests/test_models/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_models/test_connectors.py +28 -0
- mule_discovery-1.0.0/tests/test_models/test_dataweave.py +23 -0
- mule_discovery-1.0.0/tests/test_models/test_dependencies.py +28 -0
- mule_discovery-1.0.0/tests/test_models/test_flows.py +146 -0
- mule_discovery-1.0.0/tests/test_models/test_listeners.py +23 -0
- mule_discovery-1.0.0/tests/test_models/test_result.py +20 -0
- mule_discovery-1.0.0/tests/test_models/test_schemas.py +15 -0
- mule_discovery-1.0.0/tests/test_models/test_scoring.py +37 -0
- mule_discovery-1.0.0/tests/test_output/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_output/test_json_output.py +18 -0
- mule_discovery-1.0.0/tests/test_output/test_text_output.py +22 -0
- mule_discovery-1.0.0/tests/test_output/test_yaml_output.py +19 -0
- mule_discovery-1.0.0/tests/test_parsers/__init__.py +0 -0
- mule_discovery-1.0.0/tests/test_parsers/test_aws.py +328 -0
- mule_discovery-1.0.0/tests/test_parsers/test_dataweave.py +170 -0
- mule_discovery-1.0.0/tests/test_parsers/test_file_discovery.py +231 -0
- mule_discovery-1.0.0/tests/test_parsers/test_http_auth.py +291 -0
- mule_discovery-1.0.0/tests/test_parsers/test_mule_xml.py +986 -0
- mule_discovery-1.0.0/tests/test_parsers/test_openapi.py +103 -0
- mule_discovery-1.0.0/tests/test_parsers/test_pom.py +234 -0
- mule_discovery-1.0.0/tests/test_parsers/test_soap.py +356 -0
- mule_discovery-1.0.0/tests/test_parsers/test_wsdl.py +90 -0
- mule_discovery-1.0.0/tests/test_xml_helpers.py +356 -0
- mule_discovery-1.0.0/uv.lock +523 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(python -m pytest --cov=mule_discovery --cov-report=term-missing --no-header -q)",
|
|
5
|
+
"Bash(/Users/stephen.brown/projects/sandbox-workspaces/mule-discovery-tools/mule-discovery/.venv/bin/python3 -m pytest --cov=mule_discovery --cov-report=term-missing --no-header -q)",
|
|
6
|
+
"Bash(.venv/bin/python -m pytest --co -q)",
|
|
7
|
+
"Bash(.venv/bin/python -m pytest --cov=mule_discovery --cov-report=term-missing --no-header -q 2>&1)",
|
|
8
|
+
"Bash(.venv/bin/python -m pytest --cov=mule_discovery --cov-report=term-missing:skip-covered --no-header -q)",
|
|
9
|
+
"Bash(find /Users/stephen.brown/projects/sandbox-workspaces/single-app-usecase/sys-sap-plants-maintenance-api -name *.wsdl -o -name *.raml -o -name *.swagger*)",
|
|
10
|
+
"Bash(find /Users/stephen.brown/projects/sandbox-workspaces/single-app-usecase/dfi-el-agama -name *.wsdl -o -name *.raml -o -name *.swagger*)",
|
|
11
|
+
"Bash(find /Users/stephen.brown/projects/sandbox-workspaces/single-app-usecase/dfi-el-agama/src/main/resources -type f -name *.dwl)",
|
|
12
|
+
"WebFetch(domain:github.com)",
|
|
13
|
+
"Bash(gh api:*)",
|
|
14
|
+
"Bash(make test:*)",
|
|
15
|
+
"Bash(uv sync:*)"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
run: uv python install ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: uv sync --extra dev
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: uv run --extra dev python -m pytest
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python bytecode
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
|
|
16
|
+
# Testing / coverage
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
coverage.xml
|
|
21
|
+
|
|
22
|
+
# IDEs
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
|
|
29
|
+
# OS files
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
|
|
33
|
+
# Environment variables
|
|
34
|
+
.env
|
|
35
|
+
.env.*
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.PHONY: test test-verbose test-cov test-quick install clean build publish publish-test
|
|
2
|
+
|
|
3
|
+
## Install/sync dependencies
|
|
4
|
+
install:
|
|
5
|
+
uv sync --extra dev
|
|
6
|
+
|
|
7
|
+
## Run full test suite with coverage
|
|
8
|
+
test:
|
|
9
|
+
uv run --extra dev python -m pytest
|
|
10
|
+
|
|
11
|
+
## Run tests with verbose output
|
|
12
|
+
test-verbose:
|
|
13
|
+
uv run --extra dev python -m pytest -v
|
|
14
|
+
|
|
15
|
+
## Run tests without coverage (faster)
|
|
16
|
+
test-quick:
|
|
17
|
+
uv run --extra dev python -m pytest --no-cov
|
|
18
|
+
|
|
19
|
+
## Run tests and show detailed coverage report
|
|
20
|
+
test-cov:
|
|
21
|
+
uv run --extra dev python -m pytest --cov-report=html
|
|
22
|
+
@echo "HTML report: htmlcov/index.html"
|
|
23
|
+
|
|
24
|
+
## Run a specific test file (usage: make test-file F=tests/test_parsers/test_pom.py)
|
|
25
|
+
test-file:
|
|
26
|
+
uv run --extra dev python -m pytest $(F) -v --no-cov
|
|
27
|
+
|
|
28
|
+
## Run tests matching a keyword (usage: make test-k K=scoring)
|
|
29
|
+
test-k:
|
|
30
|
+
uv run --extra dev python -m pytest -k "$(K)" -v --no-cov
|
|
31
|
+
|
|
32
|
+
## Build distribution packages
|
|
33
|
+
build: clean
|
|
34
|
+
uv build
|
|
35
|
+
|
|
36
|
+
## Publish to PyPI
|
|
37
|
+
publish: build
|
|
38
|
+
UV_PUBLISH_USERNAME=__token__ \
|
|
39
|
+
UV_PUBLISH_PASSWORD=$$(python3 -c "import configparser; c = configparser.ConfigParser(); c.read('$$HOME/.pypirc'); print(c['pypi']['password'])") \
|
|
40
|
+
uv publish
|
|
41
|
+
|
|
42
|
+
## Publish to TestPyPI
|
|
43
|
+
publish-test: build
|
|
44
|
+
UV_PUBLISH_USERNAME=__token__ \
|
|
45
|
+
UV_PUBLISH_PASSWORD=$$(python3 -c "import configparser; c = configparser.ConfigParser(); c.read('$$HOME/.pypirc'); print(c['testpypi']['password'])") \
|
|
46
|
+
uv publish --publish-url https://test.pypi.org/legacy/
|
|
47
|
+
|
|
48
|
+
## Remove build artifacts and caches
|
|
49
|
+
clean:
|
|
50
|
+
rm -rf dist build htmlcov .coverage .pytest_cache
|
|
51
|
+
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
|
52
|
+
find . -type d -name "*.egg-info" -exec rm -rf {} + 2>/dev/null || true
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mule-discovery
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Scan Mule applications for migration complexity assessment
|
|
5
|
+
Project-URL: Homepage, https://github.com/KongHQ-CX/mule-discovery
|
|
6
|
+
Author: Stephen Brown
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: pyyaml>=6.0
|
|
13
|
+
Provides-Extra: anypoint
|
|
14
|
+
Requires-Dist: anypoint-sdk>=0.2.0; extra == 'anypoint'
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# mule-discovery
|
|
21
|
+
|
|
22
|
+
Scan Mule applications for migration complexity assessment.
|
|
23
|
+
|
|
24
|
+
Parses Mule 4 (and 3) XML source files, POM dependencies, DataWeave scripts, and API specifications to produce a structured migration readiness report with complexity scoring.
|
|
25
|
+
|
|
26
|
+
## Estate Analysis
|
|
27
|
+
|
|
28
|
+
The output produced by `mule-discover` (JSON or YAML) can be fed into the [estate-analyzer](https://github.com/KongHQ-CX/kong-ps-agent-skills/tree/main/mule-analysis/estate-analyzer) agent skill to generate pre-sales migration reports. The estate-analyzer processes discovery output across your entire Mule application estate to produce complexity summaries, connector frequency analysis, PoC candidate recommendations, and migration sizing reports.
|
|
29
|
+
|
|
30
|
+
## Quick Start (uv)
|
|
31
|
+
|
|
32
|
+
No install required — just run from the project directory:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd mule-discovery
|
|
36
|
+
|
|
37
|
+
# Discover all Mule apps under a directory
|
|
38
|
+
uv run mule-discover /path/to/apps --output-dir ./inventory
|
|
39
|
+
|
|
40
|
+
# JSON output instead of YAML
|
|
41
|
+
uv run mule-discover /path/to/apps --json --output-dir ./inventory
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`uv run` reads `pyproject.toml`, resolves dependencies into an ephemeral environment, and runs the command. Nothing is installed globally.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
Install dependencies with uv:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv sync
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For development (adds pytest + coverage):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv sync --extra dev
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For Anypoint Platform integration (policy scanning):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uv sync --extra anypoint
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Requires Python 3.10+.
|
|
67
|
+
|
|
68
|
+
## CLI Tools
|
|
69
|
+
|
|
70
|
+
### `mule-discover`
|
|
71
|
+
|
|
72
|
+
Recursively find all Mule applications under a directory and produce migration complexity reports for each.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Discover all apps, write YAML inventories (default) to ./inventory
|
|
76
|
+
uv run mule-discover /path/to/apps --output-dir ./inventory
|
|
77
|
+
|
|
78
|
+
# JSON output
|
|
79
|
+
uv run mule-discover /path/to/apps --json --output-dir ./inventory
|
|
80
|
+
|
|
81
|
+
# Suppress progress output
|
|
82
|
+
uv run mule-discover /path/to/apps -o ./inventory -q
|
|
83
|
+
|
|
84
|
+
# Custom complexity thresholds
|
|
85
|
+
uv run mule-discover /path/to/apps --flow-low 8 --flow-medium 18 --flow-high 30
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Each per-app report includes:
|
|
89
|
+
- Flow inventory with complexity levels (LOW / MEDIUM / HIGH / VERY_HIGH)
|
|
90
|
+
- DataWeave transformation analysis and classification
|
|
91
|
+
- HTTP listener and scheduled job detection
|
|
92
|
+
- Connector inventory with migration weights
|
|
93
|
+
- API specification detection (OpenAPI, WSDL)
|
|
94
|
+
- External dependency and out-of-scope item tracking
|
|
95
|
+
- AWS service usage (SQS, S3, DynamoDB)
|
|
96
|
+
- SOAP/WSDL service detection
|
|
97
|
+
- Overall migration score (0–100) with recommendation (SIMPLE / MODERATE / COMPLEX / VERY_COMPLEX)
|
|
98
|
+
|
|
99
|
+
### `mule-scan-policies`
|
|
100
|
+
|
|
101
|
+
Scan Anypoint Platform for API policies on deployed applications. Requires the `anypoint` extra.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install -e ".[anypoint]"
|
|
105
|
+
|
|
106
|
+
export ANYPOINT_CLIENT_ID=...
|
|
107
|
+
export ANYPOINT_CLIENT_SECRET=...
|
|
108
|
+
export ANYPOINT_ORG_ID=...
|
|
109
|
+
export ANYPOINT_ENV_ID=...
|
|
110
|
+
|
|
111
|
+
uv run mule-scan-policies
|
|
112
|
+
uv run mule-scan-policies --format json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `mule-download-policies`
|
|
116
|
+
|
|
117
|
+
Download custom policies from Anypoint Exchange. Requires the `anypoint` extra.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
export ANYPOINT_CLIENT_ID=...
|
|
121
|
+
export ANYPOINT_CLIENT_SECRET=...
|
|
122
|
+
export ANYPOINT_ORG_ID=...
|
|
123
|
+
|
|
124
|
+
uv run mule-download-policies --output-dir ./custom_policies
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Complexity Scoring
|
|
128
|
+
|
|
129
|
+
Each application receives a migration score from 0 to 100 (higher = simpler migration):
|
|
130
|
+
|
|
131
|
+
| Score Range | Recommendation | Meaning |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| 75–100 | SMALL | Straightforward migration |
|
|
134
|
+
| 50–74 | MEDIUM | Some complexity, manageable |
|
|
135
|
+
| 25–49 | LARGE | Significant effort required |
|
|
136
|
+
| 0–24 | XLARGE | Major rework needed |
|
|
137
|
+
|
|
138
|
+
Deductions are applied across eight dimensions:
|
|
139
|
+
|
|
140
|
+
| Dimension | Max Deduction |
|
|
141
|
+
|---|---|
|
|
142
|
+
| Flow complexity | 30 pts |
|
|
143
|
+
| Transform complexity | 15 pts |
|
|
144
|
+
| Risk / out-of-scope items | 20 pts |
|
|
145
|
+
| Connector migration weight | 20 pts |
|
|
146
|
+
| WSDL / SOAP services | 10 pts |
|
|
147
|
+
| Scale (flow + component count) | 20 pts |
|
|
148
|
+
| Pattern complexity (scatter-gather, choices, batch, parallel-foreach, retries) | 15 pts |
|
|
149
|
+
| DataWeave volume | 15 pts |
|
|
150
|
+
|
|
151
|
+
### Flow Complexity Thresholds
|
|
152
|
+
|
|
153
|
+
Flows are classified by component count (configurable via CLI flags):
|
|
154
|
+
|
|
155
|
+
| Components | Complexity |
|
|
156
|
+
|---|---|
|
|
157
|
+
| ≤ 6 | LOW |
|
|
158
|
+
| 7–14 | MEDIUM |
|
|
159
|
+
| 15–25 | HIGH |
|
|
160
|
+
| > 25 | VERY_HIGH |
|
|
161
|
+
|
|
162
|
+
### DataWeave Classification
|
|
163
|
+
|
|
164
|
+
DataWeave transformations are classified by line count and function usage:
|
|
165
|
+
|
|
166
|
+
| Classification | Criteria |
|
|
167
|
+
|---|---|
|
|
168
|
+
| simple_mapping | ≤ 5 lines, no complex functions |
|
|
169
|
+
| field_level_logic | 6–20 lines, or uses routine functions (map, filter, pluck, etc.) |
|
|
170
|
+
| business_logic | > 20 lines, or uses complex functions (reduce, groupBy, flatMap, etc.) |
|
|
171
|
+
|
|
172
|
+
## Package Structure
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
src/mule_discovery/
|
|
176
|
+
├── __init__.py # Main discover_mule_app() orchestrator
|
|
177
|
+
├── constants.py # XML namespaces, element classifications, connector weights
|
|
178
|
+
├── xml_helpers.py # XML utility functions
|
|
179
|
+
├── models/ # Data models (dataclasses)
|
|
180
|
+
│ ├── result.py # DiscoveryResult (top-level container)
|
|
181
|
+
│ ├── flows.py # FlowInfo, BatchInfo, ChoiceInfo, ScatterGatherInfo, ...
|
|
182
|
+
│ ├── connectors.py # ConnectorInfo, SpringDependency
|
|
183
|
+
│ ├── dataweave.py # DataWeaveInfo
|
|
184
|
+
│ ├── listeners.py # HttpListenerInfo, ScheduledJobInfo
|
|
185
|
+
│ ├── dependencies.py # ExternalDependencyInfo, SourceFiles, OutOfScopeItem
|
|
186
|
+
│ ├── schemas.py # ApiSpecInfo (OpenAPI, WSDL)
|
|
187
|
+
│ └── scoring.py # ComplexityThresholds, ScoreResult
|
|
188
|
+
├── parsers/ # File IO → models
|
|
189
|
+
│ ├── file_discovery.py # find_mule_apps(), find_mule_xml_files()
|
|
190
|
+
│ ├── mule_xml.py # Mule XML parsing (flows, listeners, jobs)
|
|
191
|
+
│ ├── pom.py # POM parsing (app name, version, connectors)
|
|
192
|
+
│ ├── http_auth.py # HTTP auth config extraction
|
|
193
|
+
│ ├── dataweave.py # DataWeave script parsing
|
|
194
|
+
│ ├── soap.py # SOAP/WSDL service detection
|
|
195
|
+
│ ├── aws.py # AWS service detection (SQS, S3, DynamoDB)
|
|
196
|
+
│ ├── openapi.py # OpenAPI spec detection
|
|
197
|
+
│ └── wsdl.py # WSDL parsing utilities
|
|
198
|
+
├── analysis/ # Models → models (pure functions)
|
|
199
|
+
│ ├── classification.py # Flow type and source category constants
|
|
200
|
+
│ ├── complexity.py # Flow and DataWeave complexity assignment
|
|
201
|
+
│ ├── patterns.py # Pattern detection (async, scatter-gather, choice, ...)
|
|
202
|
+
│ ├── scoring.py # Migration score calculation (0–100)
|
|
203
|
+
│ └── dependencies.py # External dependency and out-of-scope extraction
|
|
204
|
+
├── output/ # Models → formatted strings
|
|
205
|
+
│ ├── yaml_output.py # YAML
|
|
206
|
+
│ ├── json_output.py # JSON
|
|
207
|
+
│ └── text_output.py # Human-readable text summary
|
|
208
|
+
├── anypoint/ # Anypoint Platform integration (optional)
|
|
209
|
+
│ ├── policies.py # Policy scanning
|
|
210
|
+
│ └── exchange.py # Custom policy download
|
|
211
|
+
└── cli/ # CLI entry points (thin wrappers)
|
|
212
|
+
├── discover.py # mule-discover
|
|
213
|
+
├── scan_policies.py # mule-scan-policies
|
|
214
|
+
└── download_policies.py # mule-download-policies
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Design Principles
|
|
218
|
+
|
|
219
|
+
- **No function does both IO and computation.** Parsers read files → return models. Analysis takes models → returns models. Output takes models → returns strings.
|
|
220
|
+
- **All data models are plain dataclasses** with typed fields — no methods with side effects.
|
|
221
|
+
- **All analysis functions are standalone** — no class methods, no inheritance.
|
|
222
|
+
- **Each output format is a separate module.**
|
|
223
|
+
|
|
224
|
+
## Testing
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
make test
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Or directly:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
uv run --extra dev python -m pytest
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Coverage is enforced at 70% (branch coverage) via `pyproject.toml`.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# mule-discovery
|
|
2
|
+
|
|
3
|
+
Scan Mule applications for migration complexity assessment.
|
|
4
|
+
|
|
5
|
+
Parses Mule 4 (and 3) XML source files, POM dependencies, DataWeave scripts, and API specifications to produce a structured migration readiness report with complexity scoring.
|
|
6
|
+
|
|
7
|
+
## Estate Analysis
|
|
8
|
+
|
|
9
|
+
The output produced by `mule-discover` (JSON or YAML) can be fed into the [estate-analyzer](https://github.com/KongHQ-CX/kong-ps-agent-skills/tree/main/mule-analysis/estate-analyzer) agent skill to generate pre-sales migration reports. The estate-analyzer processes discovery output across your entire Mule application estate to produce complexity summaries, connector frequency analysis, PoC candidate recommendations, and migration sizing reports.
|
|
10
|
+
|
|
11
|
+
## Quick Start (uv)
|
|
12
|
+
|
|
13
|
+
No install required — just run from the project directory:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd mule-discovery
|
|
17
|
+
|
|
18
|
+
# Discover all Mule apps under a directory
|
|
19
|
+
uv run mule-discover /path/to/apps --output-dir ./inventory
|
|
20
|
+
|
|
21
|
+
# JSON output instead of YAML
|
|
22
|
+
uv run mule-discover /path/to/apps --json --output-dir ./inventory
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`uv run` reads `pyproject.toml`, resolves dependencies into an ephemeral environment, and runs the command. Nothing is installed globally.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Install dependencies with uv:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv sync
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For development (adds pytest + coverage):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv sync --extra dev
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For Anypoint Platform integration (policy scanning):
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv sync --extra anypoint
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Requires Python 3.10+.
|
|
48
|
+
|
|
49
|
+
## CLI Tools
|
|
50
|
+
|
|
51
|
+
### `mule-discover`
|
|
52
|
+
|
|
53
|
+
Recursively find all Mule applications under a directory and produce migration complexity reports for each.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Discover all apps, write YAML inventories (default) to ./inventory
|
|
57
|
+
uv run mule-discover /path/to/apps --output-dir ./inventory
|
|
58
|
+
|
|
59
|
+
# JSON output
|
|
60
|
+
uv run mule-discover /path/to/apps --json --output-dir ./inventory
|
|
61
|
+
|
|
62
|
+
# Suppress progress output
|
|
63
|
+
uv run mule-discover /path/to/apps -o ./inventory -q
|
|
64
|
+
|
|
65
|
+
# Custom complexity thresholds
|
|
66
|
+
uv run mule-discover /path/to/apps --flow-low 8 --flow-medium 18 --flow-high 30
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Each per-app report includes:
|
|
70
|
+
- Flow inventory with complexity levels (LOW / MEDIUM / HIGH / VERY_HIGH)
|
|
71
|
+
- DataWeave transformation analysis and classification
|
|
72
|
+
- HTTP listener and scheduled job detection
|
|
73
|
+
- Connector inventory with migration weights
|
|
74
|
+
- API specification detection (OpenAPI, WSDL)
|
|
75
|
+
- External dependency and out-of-scope item tracking
|
|
76
|
+
- AWS service usage (SQS, S3, DynamoDB)
|
|
77
|
+
- SOAP/WSDL service detection
|
|
78
|
+
- Overall migration score (0–100) with recommendation (SIMPLE / MODERATE / COMPLEX / VERY_COMPLEX)
|
|
79
|
+
|
|
80
|
+
### `mule-scan-policies`
|
|
81
|
+
|
|
82
|
+
Scan Anypoint Platform for API policies on deployed applications. Requires the `anypoint` extra.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install -e ".[anypoint]"
|
|
86
|
+
|
|
87
|
+
export ANYPOINT_CLIENT_ID=...
|
|
88
|
+
export ANYPOINT_CLIENT_SECRET=...
|
|
89
|
+
export ANYPOINT_ORG_ID=...
|
|
90
|
+
export ANYPOINT_ENV_ID=...
|
|
91
|
+
|
|
92
|
+
uv run mule-scan-policies
|
|
93
|
+
uv run mule-scan-policies --format json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `mule-download-policies`
|
|
97
|
+
|
|
98
|
+
Download custom policies from Anypoint Exchange. Requires the `anypoint` extra.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
export ANYPOINT_CLIENT_ID=...
|
|
102
|
+
export ANYPOINT_CLIENT_SECRET=...
|
|
103
|
+
export ANYPOINT_ORG_ID=...
|
|
104
|
+
|
|
105
|
+
uv run mule-download-policies --output-dir ./custom_policies
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Complexity Scoring
|
|
109
|
+
|
|
110
|
+
Each application receives a migration score from 0 to 100 (higher = simpler migration):
|
|
111
|
+
|
|
112
|
+
| Score Range | Recommendation | Meaning |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| 75–100 | SMALL | Straightforward migration |
|
|
115
|
+
| 50–74 | MEDIUM | Some complexity, manageable |
|
|
116
|
+
| 25–49 | LARGE | Significant effort required |
|
|
117
|
+
| 0–24 | XLARGE | Major rework needed |
|
|
118
|
+
|
|
119
|
+
Deductions are applied across eight dimensions:
|
|
120
|
+
|
|
121
|
+
| Dimension | Max Deduction |
|
|
122
|
+
|---|---|
|
|
123
|
+
| Flow complexity | 30 pts |
|
|
124
|
+
| Transform complexity | 15 pts |
|
|
125
|
+
| Risk / out-of-scope items | 20 pts |
|
|
126
|
+
| Connector migration weight | 20 pts |
|
|
127
|
+
| WSDL / SOAP services | 10 pts |
|
|
128
|
+
| Scale (flow + component count) | 20 pts |
|
|
129
|
+
| Pattern complexity (scatter-gather, choices, batch, parallel-foreach, retries) | 15 pts |
|
|
130
|
+
| DataWeave volume | 15 pts |
|
|
131
|
+
|
|
132
|
+
### Flow Complexity Thresholds
|
|
133
|
+
|
|
134
|
+
Flows are classified by component count (configurable via CLI flags):
|
|
135
|
+
|
|
136
|
+
| Components | Complexity |
|
|
137
|
+
|---|---|
|
|
138
|
+
| ≤ 6 | LOW |
|
|
139
|
+
| 7–14 | MEDIUM |
|
|
140
|
+
| 15–25 | HIGH |
|
|
141
|
+
| > 25 | VERY_HIGH |
|
|
142
|
+
|
|
143
|
+
### DataWeave Classification
|
|
144
|
+
|
|
145
|
+
DataWeave transformations are classified by line count and function usage:
|
|
146
|
+
|
|
147
|
+
| Classification | Criteria |
|
|
148
|
+
|---|---|
|
|
149
|
+
| simple_mapping | ≤ 5 lines, no complex functions |
|
|
150
|
+
| field_level_logic | 6–20 lines, or uses routine functions (map, filter, pluck, etc.) |
|
|
151
|
+
| business_logic | > 20 lines, or uses complex functions (reduce, groupBy, flatMap, etc.) |
|
|
152
|
+
|
|
153
|
+
## Package Structure
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
src/mule_discovery/
|
|
157
|
+
├── __init__.py # Main discover_mule_app() orchestrator
|
|
158
|
+
├── constants.py # XML namespaces, element classifications, connector weights
|
|
159
|
+
├── xml_helpers.py # XML utility functions
|
|
160
|
+
├── models/ # Data models (dataclasses)
|
|
161
|
+
│ ├── result.py # DiscoveryResult (top-level container)
|
|
162
|
+
│ ├── flows.py # FlowInfo, BatchInfo, ChoiceInfo, ScatterGatherInfo, ...
|
|
163
|
+
│ ├── connectors.py # ConnectorInfo, SpringDependency
|
|
164
|
+
│ ├── dataweave.py # DataWeaveInfo
|
|
165
|
+
│ ├── listeners.py # HttpListenerInfo, ScheduledJobInfo
|
|
166
|
+
│ ├── dependencies.py # ExternalDependencyInfo, SourceFiles, OutOfScopeItem
|
|
167
|
+
│ ├── schemas.py # ApiSpecInfo (OpenAPI, WSDL)
|
|
168
|
+
│ └── scoring.py # ComplexityThresholds, ScoreResult
|
|
169
|
+
├── parsers/ # File IO → models
|
|
170
|
+
│ ├── file_discovery.py # find_mule_apps(), find_mule_xml_files()
|
|
171
|
+
│ ├── mule_xml.py # Mule XML parsing (flows, listeners, jobs)
|
|
172
|
+
│ ├── pom.py # POM parsing (app name, version, connectors)
|
|
173
|
+
│ ├── http_auth.py # HTTP auth config extraction
|
|
174
|
+
│ ├── dataweave.py # DataWeave script parsing
|
|
175
|
+
│ ├── soap.py # SOAP/WSDL service detection
|
|
176
|
+
│ ├── aws.py # AWS service detection (SQS, S3, DynamoDB)
|
|
177
|
+
│ ├── openapi.py # OpenAPI spec detection
|
|
178
|
+
│ └── wsdl.py # WSDL parsing utilities
|
|
179
|
+
├── analysis/ # Models → models (pure functions)
|
|
180
|
+
│ ├── classification.py # Flow type and source category constants
|
|
181
|
+
│ ├── complexity.py # Flow and DataWeave complexity assignment
|
|
182
|
+
│ ├── patterns.py # Pattern detection (async, scatter-gather, choice, ...)
|
|
183
|
+
│ ├── scoring.py # Migration score calculation (0–100)
|
|
184
|
+
│ └── dependencies.py # External dependency and out-of-scope extraction
|
|
185
|
+
├── output/ # Models → formatted strings
|
|
186
|
+
│ ├── yaml_output.py # YAML
|
|
187
|
+
│ ├── json_output.py # JSON
|
|
188
|
+
│ └── text_output.py # Human-readable text summary
|
|
189
|
+
├── anypoint/ # Anypoint Platform integration (optional)
|
|
190
|
+
│ ├── policies.py # Policy scanning
|
|
191
|
+
│ └── exchange.py # Custom policy download
|
|
192
|
+
└── cli/ # CLI entry points (thin wrappers)
|
|
193
|
+
├── discover.py # mule-discover
|
|
194
|
+
├── scan_policies.py # mule-scan-policies
|
|
195
|
+
└── download_policies.py # mule-download-policies
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Design Principles
|
|
199
|
+
|
|
200
|
+
- **No function does both IO and computation.** Parsers read files → return models. Analysis takes models → returns models. Output takes models → returns strings.
|
|
201
|
+
- **All data models are plain dataclasses** with typed fields — no methods with side effects.
|
|
202
|
+
- **All analysis functions are standalone** — no class methods, no inheritance.
|
|
203
|
+
- **Each output format is a separate module.**
|
|
204
|
+
|
|
205
|
+
## Testing
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
make test
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Or directly:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
uv run --extra dev python -m pytest
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Coverage is enforced at 70% (branch coverage) via `pyproject.toml`.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mule-discovery"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "Scan Mule applications for migration complexity assessment"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [{ name = "Stephen Brown" }]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
11
|
+
"License :: OSI Approved :: MIT License",
|
|
12
|
+
"Operating System :: OS Independent",
|
|
13
|
+
]
|
|
14
|
+
dependencies = [
|
|
15
|
+
"pyyaml>=6.0",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/KongHQ-CX/mule-discovery"
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
anypoint = [
|
|
23
|
+
"anypoint-sdk>=0.2.0",
|
|
24
|
+
]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest>=7.0",
|
|
27
|
+
"pytest-cov>=4.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
mule-discover = "mule_discovery.cli.discover:main"
|
|
32
|
+
mule-scan-policies = "mule_discovery.cli.scan_policies:main"
|
|
33
|
+
mule-download-policies = "mule_discovery.cli.download_policies:main"
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["hatchling"]
|
|
37
|
+
build-backend = "hatchling.build"
|
|
38
|
+
|
|
39
|
+
[tool.pytest.ini_options]
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
addopts = "--cov=mule_discovery --cov-report=term-missing --cov-fail-under=70"
|
|
42
|
+
|
|
43
|
+
[tool.coverage.run]
|
|
44
|
+
source = ["mule_discovery"]
|
|
45
|
+
branch = true
|
|
46
|
+
|
|
47
|
+
[tool.coverage.report]
|
|
48
|
+
fail_under = 70
|
|
49
|
+
show_missing = true
|
|
50
|
+
exclude_lines = [
|
|
51
|
+
"if __name__ == .__main__.",
|
|
52
|
+
"pragma: no cover",
|
|
53
|
+
]
|