bt-cli 0.4.28__tar.gz → 0.4.29__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.
- {bt_cli-0.4.28 → bt_cli-0.4.29}/CLAUDE.md +1 -1
- {bt_cli-0.4.28 → bt_cli-0.4.29}/PKG-INFO +1 -1
- {bt_cli-0.4.28 → bt_cli-0.4.29}/pyproject.toml +1 -1
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/__init__.py +1 -1
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/configure.py +218 -2
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.claude/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.env.example +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.github/workflows/ci.yml +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.github/workflows/release.yml +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/.gitignore +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/README.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/assets/cli-help.png +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/assets/cli-output.png +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/bt-cli.spec +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/bt_entry.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/scripts/bt_entry.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/scripts/sync-package-data.sh +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/cli.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/learn.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/commands/quick.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/config.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/config_file.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/csv_utils.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/errors.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/output.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/prompts.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/core/rest_debug.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/CLAUDE.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/bt/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/entitle/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/epmw/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/pra/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/data/skills/pws/SKILL.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/client/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/client/base.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/accounts.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/applications.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/bundles.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/integrations.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/permissions.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/policies.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/resources.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/roles.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/users.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/commands/workflows.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/bundle.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/common.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/integration.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/permission.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/policy.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/resource.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/role.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/user.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/entitle/models/workflow.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/client/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/client/base.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/audits.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/computers.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/events.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/groups.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/policies.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/quick.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/requests.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/roles.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/tasks.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/commands/users.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/epmw/models/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/client/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/client/base.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/import_export.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_clients.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_groups.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jump_items.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/jumpoints.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/policies.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/quick.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/teams.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/users.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/commands/vault.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/common.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_group.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jump_item.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/jumpoint.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/team.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/user.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pra/models/vault.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/base.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/beyondinsight.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/client/passwordsafe.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/accounts.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/assets.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/attributes.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/clouds.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/config.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/credentials.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/databases.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/directories.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/functional.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/import_export.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/platforms.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/quick.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/search.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/secrets.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/systems.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/users.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/commands/workgroups.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/config.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/account.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/asset.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/common.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/src/bt_cli/pws/models/system.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/conftest.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_auth.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_config.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_errors.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/core/test_rest_debug.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/test_client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle/test_commands.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/entitle-smoke-test.sh +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/test_client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw/test_commands.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/epmw-quick-test-plan.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/fixtures/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/fixtures/responses.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/conftest.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/helpers.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_entitle_integration.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_epmw_integration.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_epmw_lifecycle.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pra_integration.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pra_lifecycle.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pws_integration.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/integration/test_pws_lifecycle.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/test_client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra/test_commands.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra-smoke-test.sh +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pra-test-plan.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/__init__.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/test_client.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws/test_commands.py +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws-quick-test-plan.md +0 -0
- {bt_cli-0.4.28 → bt_cli-0.4.29}/tests/pws-smoke-test.sh +0 -0
|
@@ -298,11 +298,21 @@ def show_config(
|
|
|
298
298
|
profile: Optional[str] = typer.Option(None, "--profile", help="Profile to show"),
|
|
299
299
|
show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
|
|
300
300
|
) -> None:
|
|
301
|
-
"""Show
|
|
301
|
+
"""Show configuration from config file.
|
|
302
|
+
|
|
303
|
+
Note: This only shows profiles saved to ~/.bt-cli/config.yaml.
|
|
304
|
+
If you're using environment variables or .env file, use:
|
|
305
|
+
|
|
306
|
+
bt configure effective
|
|
307
|
+
|
|
308
|
+
to see the actual configuration in use.
|
|
309
|
+
"""
|
|
302
310
|
config = load_config_file()
|
|
303
311
|
|
|
304
312
|
if not config.profiles:
|
|
305
|
-
print_warning("No
|
|
313
|
+
print_warning("No profiles in config file. Run 'bt configure' to set up.")
|
|
314
|
+
console.print("\n[dim]Tip: If using .env or environment variables, run:[/dim]")
|
|
315
|
+
console.print("[cyan] bt configure effective[/cyan]")
|
|
306
316
|
raise typer.Exit(0)
|
|
307
317
|
|
|
308
318
|
profiles_to_show = [profile] if profile else config.list_profiles()
|
|
@@ -413,3 +423,209 @@ def show_path() -> None:
|
|
|
413
423
|
console.print("[green]Config file exists[/green]")
|
|
414
424
|
else:
|
|
415
425
|
console.print("[yellow]Config file does not exist yet[/yellow]")
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
@app.command("import-env")
|
|
429
|
+
def import_from_env(
|
|
430
|
+
profile: str = typer.Option("default", "--profile", "-p", help="Profile name to save as"),
|
|
431
|
+
force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing profile"),
|
|
432
|
+
) -> None:
|
|
433
|
+
"""Import configuration from environment variables into a profile.
|
|
434
|
+
|
|
435
|
+
This saves the current BT_* environment variables (including .env file)
|
|
436
|
+
into a named profile in the config file. Useful for:
|
|
437
|
+
|
|
438
|
+
- Converting .env setup to profile-based config
|
|
439
|
+
- Creating profiles from existing environment
|
|
440
|
+
- Backing up current config to file
|
|
441
|
+
|
|
442
|
+
Example:
|
|
443
|
+
bt configure import-env --profile production
|
|
444
|
+
"""
|
|
445
|
+
import os
|
|
446
|
+
from dotenv import load_dotenv, find_dotenv
|
|
447
|
+
from rich.prompt import Confirm
|
|
448
|
+
|
|
449
|
+
# Load .env if present
|
|
450
|
+
env_file = find_dotenv()
|
|
451
|
+
if env_file:
|
|
452
|
+
load_dotenv(env_file)
|
|
453
|
+
console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
|
|
454
|
+
|
|
455
|
+
config = load_config_file()
|
|
456
|
+
|
|
457
|
+
# Check if profile exists
|
|
458
|
+
if profile in config.profiles and not force:
|
|
459
|
+
if not Confirm.ask(f"Profile '{profile}' exists. Overwrite?", default=False):
|
|
460
|
+
print_info("Cancelled")
|
|
461
|
+
raise typer.Exit(0)
|
|
462
|
+
|
|
463
|
+
# Product environment variable mappings
|
|
464
|
+
env_mappings = {
|
|
465
|
+
"pws": {
|
|
466
|
+
"api_url": "BT_PWS_API_URL",
|
|
467
|
+
"api_key": "BT_PWS_API_KEY",
|
|
468
|
+
"client_id": "BT_PWS_CLIENT_ID",
|
|
469
|
+
"client_secret": "BT_PWS_CLIENT_SECRET",
|
|
470
|
+
"run_as": "BT_PWS_RUN_AS",
|
|
471
|
+
"verify_ssl": "BT_PWS_VERIFY_SSL",
|
|
472
|
+
"timeout": "BT_PWS_TIMEOUT",
|
|
473
|
+
},
|
|
474
|
+
"pra": {
|
|
475
|
+
"api_url": "BT_PRA_API_URL",
|
|
476
|
+
"client_id": "BT_PRA_CLIENT_ID",
|
|
477
|
+
"client_secret": "BT_PRA_CLIENT_SECRET",
|
|
478
|
+
"verify_ssl": "BT_PRA_VERIFY_SSL",
|
|
479
|
+
"timeout": "BT_PRA_TIMEOUT",
|
|
480
|
+
},
|
|
481
|
+
"entitle": {
|
|
482
|
+
"api_url": "BT_ENTITLE_API_URL",
|
|
483
|
+
"api_key": "BT_ENTITLE_API_KEY",
|
|
484
|
+
"verify_ssl": "BT_ENTITLE_VERIFY_SSL",
|
|
485
|
+
"timeout": "BT_ENTITLE_TIMEOUT",
|
|
486
|
+
},
|
|
487
|
+
"epmw": {
|
|
488
|
+
"api_url": "BT_EPM_API_URL",
|
|
489
|
+
"client_id": "BT_EPM_CLIENT_ID",
|
|
490
|
+
"client_secret": "BT_EPM_CLIENT_SECRET",
|
|
491
|
+
"verify_ssl": "BT_EPM_VERIFY_SSL",
|
|
492
|
+
"timeout": "BT_EPM_TIMEOUT",
|
|
493
|
+
},
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
imported = []
|
|
497
|
+
for product, env_vars in env_mappings.items():
|
|
498
|
+
product_config = {}
|
|
499
|
+
for setting, env_var in env_vars.items():
|
|
500
|
+
value = os.getenv(env_var)
|
|
501
|
+
if value:
|
|
502
|
+
# Convert types
|
|
503
|
+
if setting == "verify_ssl":
|
|
504
|
+
product_config[setting] = value.lower() not in ("false", "0", "no")
|
|
505
|
+
elif setting == "timeout":
|
|
506
|
+
try:
|
|
507
|
+
product_config[setting] = float(value)
|
|
508
|
+
except ValueError:
|
|
509
|
+
product_config[setting] = 30.0
|
|
510
|
+
else:
|
|
511
|
+
product_config[setting] = value
|
|
512
|
+
|
|
513
|
+
if product_config.get("api_url"):
|
|
514
|
+
# Infer auth_method for PWS
|
|
515
|
+
if product == "pws":
|
|
516
|
+
if product_config.get("api_key"):
|
|
517
|
+
product_config["auth_method"] = "apikey"
|
|
518
|
+
elif product_config.get("client_id"):
|
|
519
|
+
product_config["auth_method"] = "oauth"
|
|
520
|
+
|
|
521
|
+
config.set_product_config(product, product_config, profile)
|
|
522
|
+
imported.append(product)
|
|
523
|
+
|
|
524
|
+
if imported:
|
|
525
|
+
if not config.default_profile or profile == "default":
|
|
526
|
+
config.default_profile = profile
|
|
527
|
+
save_config_file(config)
|
|
528
|
+
print_success(f"Imported {', '.join(imported)} into profile '{profile}'")
|
|
529
|
+
console.print(f"[dim]Config saved to: {CONFIG_FILE}[/dim]")
|
|
530
|
+
else:
|
|
531
|
+
print_warning("No configuration found in environment variables")
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
@app.command("effective")
|
|
535
|
+
def show_effective_config(
|
|
536
|
+
show_secrets: bool = typer.Option(False, "--show-secrets", help="Show secret values"),
|
|
537
|
+
) -> None:
|
|
538
|
+
"""Show effective configuration from all sources.
|
|
539
|
+
|
|
540
|
+
Shows what configuration is actually in use, combining:
|
|
541
|
+
- Environment variables (BT_PWS_*, BT_PRA_*, etc.)
|
|
542
|
+
- .env file (if present)
|
|
543
|
+
- Config file profiles (~/.bt-cli/config.yaml)
|
|
544
|
+
|
|
545
|
+
This is useful for debugging why the CLI connects successfully
|
|
546
|
+
but 'bt configure show' appears empty.
|
|
547
|
+
"""
|
|
548
|
+
import os
|
|
549
|
+
from dotenv import load_dotenv, find_dotenv
|
|
550
|
+
|
|
551
|
+
# Load .env if present
|
|
552
|
+
env_file = find_dotenv()
|
|
553
|
+
if env_file:
|
|
554
|
+
load_dotenv(env_file)
|
|
555
|
+
console.print(f"[dim]Loaded .env from: {env_file}[/dim]\n")
|
|
556
|
+
|
|
557
|
+
def mask_secret(key: str, value: str) -> str:
|
|
558
|
+
if not value:
|
|
559
|
+
return "[dim]not set[/dim]"
|
|
560
|
+
if not show_secrets and any(s in key.lower() for s in ["secret", "key", "password"]):
|
|
561
|
+
return "****" + value[-4:] if len(value) > 4 else "****"
|
|
562
|
+
return value
|
|
563
|
+
|
|
564
|
+
# Product environment variable mappings
|
|
565
|
+
products = {
|
|
566
|
+
"Password Safe": {
|
|
567
|
+
"api_url": "BT_PWS_API_URL",
|
|
568
|
+
"api_key": "BT_PWS_API_KEY",
|
|
569
|
+
"client_id": "BT_PWS_CLIENT_ID",
|
|
570
|
+
"client_secret": "BT_PWS_CLIENT_SECRET",
|
|
571
|
+
"run_as": "BT_PWS_RUN_AS",
|
|
572
|
+
"verify_ssl": "BT_PWS_VERIFY_SSL",
|
|
573
|
+
"timeout": "BT_PWS_TIMEOUT",
|
|
574
|
+
},
|
|
575
|
+
"PRA": {
|
|
576
|
+
"api_url": "BT_PRA_API_URL",
|
|
577
|
+
"client_id": "BT_PRA_CLIENT_ID",
|
|
578
|
+
"client_secret": "BT_PRA_CLIENT_SECRET",
|
|
579
|
+
"verify_ssl": "BT_PRA_VERIFY_SSL",
|
|
580
|
+
"timeout": "BT_PRA_TIMEOUT",
|
|
581
|
+
},
|
|
582
|
+
"Entitle": {
|
|
583
|
+
"api_url": "BT_ENTITLE_API_URL",
|
|
584
|
+
"api_key": "BT_ENTITLE_API_KEY",
|
|
585
|
+
"verify_ssl": "BT_ENTITLE_VERIFY_SSL",
|
|
586
|
+
"timeout": "BT_ENTITLE_TIMEOUT",
|
|
587
|
+
},
|
|
588
|
+
"EPM Windows": {
|
|
589
|
+
"api_url": "BT_EPM_API_URL",
|
|
590
|
+
"client_id": "BT_EPM_CLIENT_ID",
|
|
591
|
+
"client_secret": "BT_EPM_CLIENT_SECRET",
|
|
592
|
+
"verify_ssl": "BT_EPM_VERIFY_SSL",
|
|
593
|
+
"timeout": "BT_EPM_TIMEOUT",
|
|
594
|
+
},
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
# Check active profile
|
|
598
|
+
active_profile = os.getenv("BT_PROFILE", "default")
|
|
599
|
+
console.print(f"[bold]Active Profile:[/bold] {active_profile}\n")
|
|
600
|
+
|
|
601
|
+
# Show effective config for each product
|
|
602
|
+
for product_name, env_vars in products.items():
|
|
603
|
+
table = Table(title=product_name, show_header=True, title_style="bold cyan")
|
|
604
|
+
table.add_column("Setting", style="green")
|
|
605
|
+
table.add_column("Env Var", style="dim")
|
|
606
|
+
table.add_column("Value")
|
|
607
|
+
table.add_column("Source", style="dim")
|
|
608
|
+
|
|
609
|
+
has_config = False
|
|
610
|
+
for setting, env_var in env_vars.items():
|
|
611
|
+
value = os.getenv(env_var, "")
|
|
612
|
+
if value:
|
|
613
|
+
has_config = True
|
|
614
|
+
source = ".env" if env_file else "environment"
|
|
615
|
+
table.add_row(setting, env_var, mask_secret(setting, value), source)
|
|
616
|
+
|
|
617
|
+
if has_config:
|
|
618
|
+
console.print(table)
|
|
619
|
+
console.print()
|
|
620
|
+
else:
|
|
621
|
+
console.print(f"[dim]{product_name}: not configured[/dim]\n")
|
|
622
|
+
|
|
623
|
+
# Also show config file info
|
|
624
|
+
config = load_config_file()
|
|
625
|
+
if config.profiles:
|
|
626
|
+
console.print("[bold]Config File Profiles:[/bold]")
|
|
627
|
+
for profile_name in config.list_profiles():
|
|
628
|
+
products_list = list(config.profiles[profile_name].keys())
|
|
629
|
+
is_default = " (default)" if profile_name == config.default_profile else ""
|
|
630
|
+
console.print(f" {profile_name}{is_default}: {', '.join(products_list)}")
|
|
631
|
+
console.print(f"\n[dim]Note: Environment variables override config file settings[/dim]")
|
|
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
|
|
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
|
|
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
|