nextmv 1.1.3.dev1__tar.gz → 1.1.3.dev2__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.
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/PKG-INFO +1 -1
- nextmv-1.1.3.dev2/nextmv/__about__.py +1 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/mcp/server.py +115 -7
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cli/test_mcp.py +112 -2
- nextmv-1.1.3.dev1/nextmv/__about__.py +0 -1
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/.gitignore +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/.python-version +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/LICENSE +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/README.md +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/__entrypoint__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/_serialization.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/base_model.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/CONTRIBUTING.md +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/acceptance/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/account/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/account/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/account/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/account/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/account/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/exists.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/push.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/app/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/batch/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/data/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/data/upload.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/ensemble/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/input_set/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/exists.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/instance/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/managed_input/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/app/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/app/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/app/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/app/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/app/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/version/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/version/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/version/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/version/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/version/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/cancel.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/input.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/logs.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/run/track.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/scenario/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/secrets/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/start.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/stop.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/shadow/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/disable.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/enable.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/sso/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/start.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/stop.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/switchback/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/upload/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/upload/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/exists.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/version/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/community/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/community/clone.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/community/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/configuration/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/configuration/config.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/configuration/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/configuration/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/configuration/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/confirm.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/delete.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/register.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/registered.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/sync.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/app/update.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/create.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/get.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/input.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/list.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/logs.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/metadata.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/local/run/visuals.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/main.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/mcp/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/mcp/serve.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/message.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/options.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/version.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/acceptance_test.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/account.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_acceptance.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_batch_scenario.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_ensemble.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_input_set.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_instance.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_managed_input.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_run.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_secrets.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_shadow.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_switchback.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_utils.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/application/_version.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/assets.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/batch_experiment.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/client.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/community.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/ensemble.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/input_set.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/instance.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/integration.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/marketplace.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/package.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/scenario.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/secrets.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/shadow.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/sso.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/switchback.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/url.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cloud/version.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/.gitignore +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/README.md +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/app.yaml +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/input.json +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/main.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/requirements.txt +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/src/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/default_app/src/visuals.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/deprecated.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/input.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/application.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/executor.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/geojson_handler.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/local.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/plotly_handler.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/registry.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/local/runner.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/logger.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/manifest.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/model.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/options.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/output.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/polling.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/run.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/safe.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/status.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/pyproject.toml +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/README.md +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cli/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cli/test_configuration.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cli/test_main.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cli/test_version.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/app.yaml +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/test_client.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/test_instance.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/test_package.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/cloud/test_scenario.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/integration/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/integration/cloud/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/integration/cloud/test_integration_cloud.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/integration/cloud/test_integration_marketplace.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/local/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/local/test_application.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/local/test_executor.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/local/test_registry.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/local/test_runner.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options1.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options2.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options3.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options4.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options5.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options6.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/scripts/options7.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_base_model.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_entrypoint/__init__.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_entrypoint/test_entrypoint.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_input.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_inputs/test_data.csv +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_inputs/test_data.json +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_inputs/test_data.txt +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_logger.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_manifest.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_model.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_options.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_output.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_polling.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_run.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_safe.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_serialization.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/tests/test_version.py +0 -0
- {nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/uv.lock +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "v1.1.3.dev2"
|
|
@@ -17,12 +17,32 @@ from nextmv.cloud import (
|
|
|
17
17
|
)
|
|
18
18
|
from nextmv.polling import default_polling_options
|
|
19
19
|
|
|
20
|
+
# Session-level profile. None means "default" (top-level config keys).
|
|
21
|
+
_current_profile: str | None = None
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
|
|
24
|
+
def _mask_key(key: str | None) -> str | None:
|
|
25
|
+
"""Mask an API key, keeping only the last 4 characters visible."""
|
|
26
|
+
|
|
27
|
+
if not key:
|
|
28
|
+
return None
|
|
29
|
+
if len(key) <= 4:
|
|
30
|
+
return key
|
|
31
|
+
return "X" * (len(key) - 4) + key[-4:]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _get_client(profile: str | None = None) -> Client:
|
|
35
|
+
"""Build a Cloud client from env var or CLI config.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
profile: Optional profile override. If not provided, uses the
|
|
39
|
+
session-level ``_current_profile``.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
resolved = profile or _current_profile
|
|
23
43
|
|
|
24
44
|
api_key = os.getenv("NEXTMV_API_KEY")
|
|
25
|
-
if api_key:
|
|
45
|
+
if api_key and not resolved:
|
|
26
46
|
endpoint = os.getenv("NEXTMV_ENDPOINT", "https://api.cloud.nextmv.io")
|
|
27
47
|
if not endpoint.startswith("http"):
|
|
28
48
|
endpoint = f"https://{endpoint}"
|
|
@@ -32,7 +52,9 @@ def _get_client() -> Client:
|
|
|
32
52
|
try:
|
|
33
53
|
from nextmv.cli.configuration.config import build_client
|
|
34
54
|
|
|
35
|
-
|
|
55
|
+
# "default" means use top-level keys (profile=None in build_client).
|
|
56
|
+
p = None if resolved is None or resolved == "default" else resolved
|
|
57
|
+
return build_client(profile=p)
|
|
36
58
|
except Exception as e:
|
|
37
59
|
raise ValueError(
|
|
38
60
|
"No Nextmv API key found. Either set the NEXTMV_API_KEY "
|
|
@@ -41,10 +63,10 @@ def _get_client() -> Client:
|
|
|
41
63
|
) from e
|
|
42
64
|
|
|
43
65
|
|
|
44
|
-
def _get_app(app_id: str) -> Application:
|
|
66
|
+
def _get_app(app_id: str, profile: str | None = None) -> Application:
|
|
45
67
|
"""Build a cloud Application handle for the given ID."""
|
|
46
68
|
|
|
47
|
-
client = _get_client()
|
|
69
|
+
client = _get_client(profile=profile)
|
|
48
70
|
return Application(client=client, id=app_id)
|
|
49
71
|
|
|
50
72
|
|
|
@@ -69,6 +91,83 @@ def _save_to_file(data: Any, prefix: str) -> str:
|
|
|
69
91
|
return f"Data saved to {path} — use file-reading tools to inspect the contents."
|
|
70
92
|
|
|
71
93
|
|
|
94
|
+
# ════════════════════════════════════════════════════════════════
|
|
95
|
+
# Cloud: Profile management
|
|
96
|
+
# ════════════════════════════════════════════════════════════════
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _register_profile_tools(mcp: FastMCP) -> None:
|
|
100
|
+
"""Register profile management tools."""
|
|
101
|
+
|
|
102
|
+
@mcp.tool()
|
|
103
|
+
def cloud_list_profiles() -> list[dict[str, str | None]]:
|
|
104
|
+
"""List available Nextmv Cloud profiles from ~/.nextmv/config.yaml.
|
|
105
|
+
|
|
106
|
+
Returns a list of profiles. Each profile has a name, endpoint,
|
|
107
|
+
and a masked API key (last 4 characters visible).
|
|
108
|
+
The "default" profile uses the top-level configuration keys.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
from nextmv.cli.configuration.config import (
|
|
112
|
+
API_KEY_KEY,
|
|
113
|
+
ENDPOINT_KEY,
|
|
114
|
+
load_config,
|
|
115
|
+
non_profile_keys,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
config = load_config()
|
|
119
|
+
profiles: list[dict[str, str | None]] = []
|
|
120
|
+
|
|
121
|
+
# Add the default profile (top-level keys).
|
|
122
|
+
if config:
|
|
123
|
+
profiles.append(
|
|
124
|
+
{
|
|
125
|
+
"name": "default",
|
|
126
|
+
"endpoint": config.get(ENDPOINT_KEY),
|
|
127
|
+
"api_key": _mask_key(config.get(API_KEY_KEY)),
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Add named profiles.
|
|
132
|
+
reserved = non_profile_keys()
|
|
133
|
+
for key, value in config.items():
|
|
134
|
+
if key in reserved:
|
|
135
|
+
continue
|
|
136
|
+
if isinstance(value, dict):
|
|
137
|
+
profiles.append(
|
|
138
|
+
{
|
|
139
|
+
"name": key,
|
|
140
|
+
"endpoint": value.get(ENDPOINT_KEY),
|
|
141
|
+
"api_key": _mask_key(value.get(API_KEY_KEY)),
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return profiles
|
|
146
|
+
|
|
147
|
+
@mcp.tool()
|
|
148
|
+
def cloud_set_profile(profile: str) -> str:
|
|
149
|
+
"""Set the active Nextmv Cloud profile for this session.
|
|
150
|
+
|
|
151
|
+
All subsequent cloud tool calls will use this profile's
|
|
152
|
+
credentials unless overridden. Use "default" to switch back
|
|
153
|
+
to the default profile.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
profile: Profile name from ~/.nextmv/config.yaml, or
|
|
157
|
+
"default" for the top-level configuration.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
global _current_profile
|
|
161
|
+
_current_profile = None if profile == "default" else profile
|
|
162
|
+
return f"Active profile set to \"{profile}\"."
|
|
163
|
+
|
|
164
|
+
@mcp.tool()
|
|
165
|
+
def cloud_get_profile() -> str:
|
|
166
|
+
"""Get the currently active Nextmv Cloud profile name."""
|
|
167
|
+
|
|
168
|
+
return _current_profile or "default"
|
|
169
|
+
|
|
170
|
+
|
|
72
171
|
# ════════════════════════════════════════════════════════════════
|
|
73
172
|
# Cloud: App management
|
|
74
173
|
# ════════════════════════════════════════════════════════════════
|
|
@@ -1790,11 +1889,20 @@ def create_server() -> FastMCP:
|
|
|
1790
1889
|
"inputs, logs) are automatically saved to local temp files to "
|
|
1791
1890
|
"keep the context window small — the tool will return the file "
|
|
1792
1891
|
"path so you can selectively read what you need. Large inputs "
|
|
1793
|
-
"can be passed directly as tool parameters without concern
|
|
1892
|
+
"can be passed directly as tool parameters without concern.\n\n"
|
|
1893
|
+
"PROFILES: The server supports multiple profiles from "
|
|
1894
|
+
"~/.nextmv/config.yaml. Use cloud_list_profiles to see "
|
|
1895
|
+
"available profiles and cloud_set_profile to switch. The "
|
|
1896
|
+
"default profile is used unless changed. When the user asks "
|
|
1897
|
+
"to use a specific profile (e.g. \"list apps in my dev "
|
|
1898
|
+
"profile\"), call cloud_set_profile first. Always state which "
|
|
1899
|
+
"profile you are using when calling cloud tools, e.g. "
|
|
1900
|
+
"(profile: \"default\")."
|
|
1794
1901
|
),
|
|
1795
1902
|
)
|
|
1796
1903
|
|
|
1797
1904
|
# Cloud tools
|
|
1905
|
+
_register_profile_tools(mcp)
|
|
1798
1906
|
_register_app_tools(mcp)
|
|
1799
1907
|
_register_run_tools(mcp)
|
|
1800
1908
|
_register_version_tools(mcp)
|
|
@@ -71,6 +71,15 @@ class TestMCPServerTools(unittest.TestCase):
|
|
|
71
71
|
server = create_server()
|
|
72
72
|
self.assertEqual(server.name, "nextmv")
|
|
73
73
|
|
|
74
|
+
def test_server_has_all_profile_tools(self):
|
|
75
|
+
"""Test that profile tools are registered."""
|
|
76
|
+
from nextmv.cli.mcp.server import create_server
|
|
77
|
+
|
|
78
|
+
server = create_server()
|
|
79
|
+
tool_names = list(server._tool_manager._tools.keys())
|
|
80
|
+
for name in ["cloud_list_profiles", "cloud_set_profile", "cloud_get_profile"]:
|
|
81
|
+
self.assertIn(name, tool_names, f"Missing tool: {name}")
|
|
82
|
+
|
|
74
83
|
def test_server_has_all_cloud_app_tools(self):
|
|
75
84
|
"""Test that cloud app tools are registered."""
|
|
76
85
|
from nextmv.cli.mcp.server import create_server
|
|
@@ -238,8 +247,8 @@ class TestMCPServerTools(unittest.TestCase):
|
|
|
238
247
|
|
|
239
248
|
server = create_server()
|
|
240
249
|
tool_names = list(server._tool_manager._tools.keys())
|
|
241
|
-
# Should have
|
|
242
|
-
self.assertGreaterEqual(len(tool_names),
|
|
250
|
+
# Should have 68+ tools covering all CLI commands.
|
|
251
|
+
self.assertGreaterEqual(len(tool_names), 68, f"Only {len(tool_names)} tools registered")
|
|
243
252
|
|
|
244
253
|
@patch("nextmv.cli.mcp.server._get_client")
|
|
245
254
|
def test_cloud_list_apps_calls_sdk(self, mock_get_client):
|
|
@@ -510,3 +519,104 @@ class TestSaveToFile(unittest.TestCase):
|
|
|
510
519
|
# Second scenario: explicit type + list config.
|
|
511
520
|
self.assertEqual(scenarios[1].scenario_input.scenario_input_data, "other-set")
|
|
512
521
|
self.assertEqual(scenarios[1].configuration[0].values, ["10", "30"])
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
class TestProfiles(unittest.TestCase):
|
|
525
|
+
"""Tests for profile management tools."""
|
|
526
|
+
|
|
527
|
+
def test_mask_key(self):
|
|
528
|
+
"""Test that _mask_key masks all but the last 4 characters."""
|
|
529
|
+
from nextmv.cli.mcp.server import _mask_key
|
|
530
|
+
|
|
531
|
+
self.assertIsNone(_mask_key(None))
|
|
532
|
+
self.assertEqual(_mask_key("abcd"), "abcd")
|
|
533
|
+
self.assertEqual(_mask_key("abcde12345"), "XXXXXX2345")
|
|
534
|
+
|
|
535
|
+
def test_set_and_get_profile(self):
|
|
536
|
+
"""Test that cloud_set_profile and cloud_get_profile work together."""
|
|
537
|
+
import nextmv.cli.mcp.server as srv
|
|
538
|
+
from nextmv.cli.mcp.server import create_server
|
|
539
|
+
|
|
540
|
+
server = create_server()
|
|
541
|
+
set_tool = server._tool_manager._tools["cloud_set_profile"]
|
|
542
|
+
get_tool = server._tool_manager._tools["cloud_get_profile"]
|
|
543
|
+
|
|
544
|
+
# Default profile.
|
|
545
|
+
result = asyncio.run(get_tool.run({}))
|
|
546
|
+
text = json.loads(result[0].text) if hasattr(result[0], "text") else str(result)
|
|
547
|
+
self.assertIn("default", str(text))
|
|
548
|
+
|
|
549
|
+
# Switch to a named profile.
|
|
550
|
+
asyncio.run(set_tool.run({"profile": "staging"}))
|
|
551
|
+
self.assertEqual(srv._current_profile, "staging")
|
|
552
|
+
|
|
553
|
+
result = asyncio.run(get_tool.run({}))
|
|
554
|
+
text = json.loads(result[0].text) if hasattr(result[0], "text") else str(result)
|
|
555
|
+
self.assertIn("staging", str(text))
|
|
556
|
+
|
|
557
|
+
# Switch back to default.
|
|
558
|
+
asyncio.run(set_tool.run({"profile": "default"}))
|
|
559
|
+
self.assertIsNone(srv._current_profile)
|
|
560
|
+
|
|
561
|
+
def test_list_profiles(self):
|
|
562
|
+
"""Test that cloud_list_profiles reads config correctly."""
|
|
563
|
+
from nextmv.cli.mcp.server import create_server
|
|
564
|
+
|
|
565
|
+
mock_config = {
|
|
566
|
+
"apikey": "my-secret-key-1234",
|
|
567
|
+
"endpoint": "api.cloud.nextmv.io",
|
|
568
|
+
"staging": {
|
|
569
|
+
"apikey": "stg-key-5678",
|
|
570
|
+
"endpoint": "staging.api.nextmv.io",
|
|
571
|
+
},
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
with patch(
|
|
575
|
+
"nextmv.cli.configuration.config.load_config",
|
|
576
|
+
return_value=mock_config,
|
|
577
|
+
):
|
|
578
|
+
server = create_server()
|
|
579
|
+
tool = server._tool_manager._tools["cloud_list_profiles"]
|
|
580
|
+
result = asyncio.run(tool.run({}))
|
|
581
|
+
profiles = json.loads(result[0].text) if hasattr(result[0], "text") else result
|
|
582
|
+
self.assertEqual(len(profiles), 2)
|
|
583
|
+
self.assertEqual(profiles[0]["name"], "default")
|
|
584
|
+
self.assertEqual(profiles[0]["endpoint"], "api.cloud.nextmv.io")
|
|
585
|
+
self.assertIn("1234", profiles[0]["api_key"])
|
|
586
|
+
self.assertNotIn("my-secret", profiles[0]["api_key"])
|
|
587
|
+
self.assertEqual(profiles[1]["name"], "staging")
|
|
588
|
+
self.assertIn("5678", profiles[1]["api_key"])
|
|
589
|
+
|
|
590
|
+
@patch.dict("os.environ", {}, clear=True)
|
|
591
|
+
@patch("nextmv.cli.configuration.config.build_client")
|
|
592
|
+
def test_get_client_uses_profile(self, mock_build_client):
|
|
593
|
+
"""Test that _get_client passes the profile to build_client."""
|
|
594
|
+
import nextmv.cli.mcp.server as srv
|
|
595
|
+
from nextmv.cli.mcp.server import _get_client
|
|
596
|
+
|
|
597
|
+
mock_build_client.return_value = MagicMock()
|
|
598
|
+
|
|
599
|
+
# Explicit profile override.
|
|
600
|
+
_get_client(profile="staging")
|
|
601
|
+
mock_build_client.assert_called_with(profile="staging")
|
|
602
|
+
|
|
603
|
+
# Session-level profile.
|
|
604
|
+
srv._current_profile = "prod"
|
|
605
|
+
_get_client()
|
|
606
|
+
mock_build_client.assert_called_with(profile="prod")
|
|
607
|
+
|
|
608
|
+
# Reset.
|
|
609
|
+
srv._current_profile = None
|
|
610
|
+
|
|
611
|
+
@patch.dict("os.environ", {"NEXTMV_API_KEY": "env-key"}, clear=False)
|
|
612
|
+
def test_get_client_env_skipped_when_profile_set(self):
|
|
613
|
+
"""Test that env var is skipped when a profile is active."""
|
|
614
|
+
import nextmv.cli.mcp.server as srv
|
|
615
|
+
from nextmv.cli.mcp.server import _get_client
|
|
616
|
+
|
|
617
|
+
with patch("nextmv.cli.configuration.config.build_client") as mock_build:
|
|
618
|
+
mock_build.return_value = MagicMock()
|
|
619
|
+
srv._current_profile = "staging"
|
|
620
|
+
_get_client()
|
|
621
|
+
mock_build.assert_called_with(profile="staging")
|
|
622
|
+
srv._current_profile = None
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "v1.1.3.dev1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nextmv-1.1.3.dev1 → nextmv-1.1.3.dev2}/nextmv/cli/cloud/marketplace/subscription/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|