bt-cli 0.4.7__py3-none-any.whl

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.
Files changed (121) hide show
  1. bt_cli/__init__.py +3 -0
  2. bt_cli/cli.py +830 -0
  3. bt_cli/commands/__init__.py +1 -0
  4. bt_cli/commands/configure.py +415 -0
  5. bt_cli/commands/learn.py +229 -0
  6. bt_cli/commands/quick.py +784 -0
  7. bt_cli/core/__init__.py +1 -0
  8. bt_cli/core/auth.py +213 -0
  9. bt_cli/core/client.py +313 -0
  10. bt_cli/core/config.py +393 -0
  11. bt_cli/core/config_file.py +420 -0
  12. bt_cli/core/csv_utils.py +91 -0
  13. bt_cli/core/errors.py +247 -0
  14. bt_cli/core/output.py +205 -0
  15. bt_cli/core/prompts.py +87 -0
  16. bt_cli/core/rest_debug.py +221 -0
  17. bt_cli/data/CLAUDE.md +88 -0
  18. bt_cli/data/__init__.py +0 -0
  19. bt_cli/data/skills/bt/SKILL.md +98 -0
  20. bt_cli/data/skills/entitle/SKILL.md +159 -0
  21. bt_cli/data/skills/epmw/SKILL.md +145 -0
  22. bt_cli/data/skills/pra/SKILL.md +149 -0
  23. bt_cli/data/skills/pws/SKILL.md +197 -0
  24. bt_cli/entitle/__init__.py +1 -0
  25. bt_cli/entitle/client/__init__.py +5 -0
  26. bt_cli/entitle/client/base.py +443 -0
  27. bt_cli/entitle/commands/__init__.py +24 -0
  28. bt_cli/entitle/commands/accounts.py +53 -0
  29. bt_cli/entitle/commands/applications.py +39 -0
  30. bt_cli/entitle/commands/auth.py +68 -0
  31. bt_cli/entitle/commands/bundles.py +218 -0
  32. bt_cli/entitle/commands/integrations.py +60 -0
  33. bt_cli/entitle/commands/permissions.py +70 -0
  34. bt_cli/entitle/commands/policies.py +97 -0
  35. bt_cli/entitle/commands/resources.py +131 -0
  36. bt_cli/entitle/commands/roles.py +74 -0
  37. bt_cli/entitle/commands/users.py +123 -0
  38. bt_cli/entitle/commands/workflows.py +187 -0
  39. bt_cli/entitle/models/__init__.py +31 -0
  40. bt_cli/entitle/models/bundle.py +28 -0
  41. bt_cli/entitle/models/common.py +37 -0
  42. bt_cli/entitle/models/integration.py +30 -0
  43. bt_cli/entitle/models/permission.py +27 -0
  44. bt_cli/entitle/models/policy.py +25 -0
  45. bt_cli/entitle/models/resource.py +29 -0
  46. bt_cli/entitle/models/role.py +28 -0
  47. bt_cli/entitle/models/user.py +24 -0
  48. bt_cli/entitle/models/workflow.py +55 -0
  49. bt_cli/epmw/__init__.py +1 -0
  50. bt_cli/epmw/client/__init__.py +5 -0
  51. bt_cli/epmw/client/base.py +848 -0
  52. bt_cli/epmw/commands/__init__.py +33 -0
  53. bt_cli/epmw/commands/audits.py +250 -0
  54. bt_cli/epmw/commands/auth.py +55 -0
  55. bt_cli/epmw/commands/computers.py +140 -0
  56. bt_cli/epmw/commands/events.py +233 -0
  57. bt_cli/epmw/commands/groups.py +215 -0
  58. bt_cli/epmw/commands/policies.py +673 -0
  59. bt_cli/epmw/commands/quick.py +348 -0
  60. bt_cli/epmw/commands/requests.py +224 -0
  61. bt_cli/epmw/commands/roles.py +78 -0
  62. bt_cli/epmw/commands/tasks.py +38 -0
  63. bt_cli/epmw/commands/users.py +219 -0
  64. bt_cli/epmw/models/__init__.py +1 -0
  65. bt_cli/pra/__init__.py +1 -0
  66. bt_cli/pra/client/__init__.py +5 -0
  67. bt_cli/pra/client/base.py +618 -0
  68. bt_cli/pra/commands/__init__.py +30 -0
  69. bt_cli/pra/commands/auth.py +55 -0
  70. bt_cli/pra/commands/import_export.py +442 -0
  71. bt_cli/pra/commands/jump_clients.py +139 -0
  72. bt_cli/pra/commands/jump_groups.py +146 -0
  73. bt_cli/pra/commands/jump_items.py +638 -0
  74. bt_cli/pra/commands/jumpoints.py +95 -0
  75. bt_cli/pra/commands/policies.py +197 -0
  76. bt_cli/pra/commands/quick.py +470 -0
  77. bt_cli/pra/commands/teams.py +81 -0
  78. bt_cli/pra/commands/users.py +87 -0
  79. bt_cli/pra/commands/vault.py +564 -0
  80. bt_cli/pra/models/__init__.py +27 -0
  81. bt_cli/pra/models/common.py +12 -0
  82. bt_cli/pra/models/jump_client.py +25 -0
  83. bt_cli/pra/models/jump_group.py +15 -0
  84. bt_cli/pra/models/jump_item.py +72 -0
  85. bt_cli/pra/models/jumpoint.py +19 -0
  86. bt_cli/pra/models/team.py +14 -0
  87. bt_cli/pra/models/user.py +17 -0
  88. bt_cli/pra/models/vault.py +45 -0
  89. bt_cli/pws/__init__.py +1 -0
  90. bt_cli/pws/client/__init__.py +5 -0
  91. bt_cli/pws/client/base.py +356 -0
  92. bt_cli/pws/client/beyondinsight.py +869 -0
  93. bt_cli/pws/client/passwordsafe.py +1786 -0
  94. bt_cli/pws/commands/__init__.py +33 -0
  95. bt_cli/pws/commands/accounts.py +372 -0
  96. bt_cli/pws/commands/assets.py +311 -0
  97. bt_cli/pws/commands/auth.py +166 -0
  98. bt_cli/pws/commands/clouds.py +221 -0
  99. bt_cli/pws/commands/config.py +344 -0
  100. bt_cli/pws/commands/credentials.py +347 -0
  101. bt_cli/pws/commands/databases.py +306 -0
  102. bt_cli/pws/commands/directories.py +199 -0
  103. bt_cli/pws/commands/functional.py +298 -0
  104. bt_cli/pws/commands/import_export.py +452 -0
  105. bt_cli/pws/commands/platforms.py +118 -0
  106. bt_cli/pws/commands/quick.py +1646 -0
  107. bt_cli/pws/commands/search.py +256 -0
  108. bt_cli/pws/commands/secrets.py +1343 -0
  109. bt_cli/pws/commands/systems.py +389 -0
  110. bt_cli/pws/commands/users.py +415 -0
  111. bt_cli/pws/commands/workgroups.py +166 -0
  112. bt_cli/pws/config.py +18 -0
  113. bt_cli/pws/models/__init__.py +19 -0
  114. bt_cli/pws/models/account.py +186 -0
  115. bt_cli/pws/models/asset.py +102 -0
  116. bt_cli/pws/models/common.py +132 -0
  117. bt_cli/pws/models/system.py +121 -0
  118. bt_cli-0.4.7.dist-info/METADATA +172 -0
  119. bt_cli-0.4.7.dist-info/RECORD +121 -0
  120. bt_cli-0.4.7.dist-info/WHEEL +4 -0
  121. bt_cli-0.4.7.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,33 @@
1
+ """EPMW commands module."""
2
+
3
+ import typer
4
+
5
+ from .auth import app as auth_app
6
+ from .computers import app as computers_app
7
+ from .groups import app as groups_app
8
+ from .policies import app as policies_app
9
+ from .roles import app as roles_app
10
+ from .users import app as users_app
11
+ from .requests import app as requests_app
12
+ from .audits import app as audits_app
13
+ from .tasks import app as tasks_app
14
+ from .events import app as events_app
15
+ from .quick import app as quick_app
16
+
17
+ app = typer.Typer(
18
+ name="epmw",
19
+ help="EPM Windows endpoint privilege management",
20
+ no_args_is_help=True,
21
+ )
22
+
23
+ app.add_typer(auth_app, name="auth")
24
+ app.add_typer(computers_app, name="computers")
25
+ app.add_typer(groups_app, name="groups")
26
+ app.add_typer(policies_app, name="policies")
27
+ app.add_typer(roles_app, name="roles")
28
+ app.add_typer(users_app, name="users")
29
+ app.add_typer(requests_app, name="requests")
30
+ app.add_typer(audits_app, name="audits")
31
+ app.add_typer(tasks_app, name="tasks")
32
+ app.add_typer(events_app, name="events")
33
+ app.add_typer(quick_app, name="quick", help="Quick commands - common multi-step operations")
@@ -0,0 +1,250 @@
1
+ """EPMW audit commands."""
2
+
3
+ import httpx
4
+ import typer
5
+
6
+ from bt_cli.core.output import OutputFormat, print_api_error, print_json, print_table
7
+
8
+ app = typer.Typer(no_args_is_help=True, help="Audit logs and history")
9
+
10
+ # Nested typer apps for audit types
11
+ activity_app = typer.Typer(no_args_is_help=True, help="Activity audit records")
12
+ authorization_app = typer.Typer(no_args_is_help=True, help="Authorization requests")
13
+ requests_app = typer.Typer(no_args_is_help=True, help="Authorization request audits")
14
+
15
+ app.add_typer(activity_app, name="activity", help="Activity audit records")
16
+ app.add_typer(authorization_app, name="authorization", help="Authorization requests")
17
+ app.add_typer(requests_app, name="requests", help="Authorization request audits")
18
+
19
+
20
+ # Activity audits
21
+ @activity_app.command("list")
22
+ def list_activity_audits(
23
+ output: OutputFormat = typer.Option(
24
+ OutputFormat.TABLE, "--output", "-o", help="Output format"
25
+ ),
26
+ ):
27
+ """List activity audit records."""
28
+ from bt_cli.epmw.client import get_client
29
+
30
+ try:
31
+ client = get_client()
32
+ audits = client.list_activity_audits()
33
+
34
+ if output == OutputFormat.JSON:
35
+ print_json(audits)
36
+ else:
37
+ columns = [
38
+ ("ID", "id"),
39
+ ("Entity", "entity"),
40
+ ("Entity Name", "entityName"),
41
+ ("Type", "auditType"),
42
+ ("Changed By", "changedBy"),
43
+ ("Created", "created"),
44
+ ]
45
+ print_table(audits, columns, title="Activity Audits")
46
+ except httpx.HTTPStatusError as e:
47
+ print_api_error(e, "list activity audits")
48
+ raise typer.Exit(1)
49
+ except httpx.RequestError as e:
50
+ print_api_error(e, "list activity audits")
51
+ raise typer.Exit(1)
52
+ except Exception as e:
53
+ print_api_error(e, "list activity audits")
54
+ raise typer.Exit(1)
55
+
56
+
57
+ @activity_app.command("get")
58
+ def get_activity_audit(
59
+ audit_id: int = typer.Argument(..., help="Audit ID"),
60
+ output: OutputFormat = typer.Option(
61
+ OutputFormat.JSON, "--output", "-o", help="Output format"
62
+ ),
63
+ ):
64
+ """Get activity audit details."""
65
+ from bt_cli.epmw.client import get_client
66
+
67
+ try:
68
+ client = get_client()
69
+ audit = client.get_activity_audit(audit_id)
70
+
71
+ if output == OutputFormat.JSON:
72
+ print_json(audit)
73
+ else:
74
+ typer.echo(f"ID: {audit.get('id')}")
75
+ typer.echo(f"Entity: {audit.get('entity')}")
76
+ typer.echo(f"Entity Name: {audit.get('entityName')}")
77
+ typer.echo(f"Type: {audit.get('auditType')}")
78
+ typer.echo(f"Changed By: {audit.get('changedBy')}")
79
+ typer.echo(f"User: {audit.get('user')}")
80
+ typer.echo(f"Created: {audit.get('created')}")
81
+ typer.echo(f"Details: {audit.get('details')}")
82
+ except httpx.HTTPStatusError as e:
83
+ print_api_error(e, "get activity audit")
84
+ raise typer.Exit(1)
85
+ except httpx.RequestError as e:
86
+ print_api_error(e, "get activity audit")
87
+ raise typer.Exit(1)
88
+ except Exception as e:
89
+ print_api_error(e, "get activity audit")
90
+ raise typer.Exit(1)
91
+
92
+
93
+ # Authorization requests (JIT app requests)
94
+ @authorization_app.command("list")
95
+ def list_authorization_requests(
96
+ output: OutputFormat = typer.Option(
97
+ OutputFormat.TABLE, "--output", "-o", help="Output format"
98
+ ),
99
+ ):
100
+ """List authorization requests (JIT app requests)."""
101
+ from bt_cli.epmw.client import get_client
102
+
103
+ try:
104
+ client = get_client()
105
+ requests = client.list_authorization_requests()
106
+
107
+ if output == OutputFormat.JSON:
108
+ print_json(requests)
109
+ else:
110
+ # Flatten nested structure for table display
111
+ rows = []
112
+ for req in requests:
113
+ info = req.get("requestInfo", {})
114
+ decision = req.get("accessDecision", {})
115
+ ticket = req.get("serviceTicket", {})
116
+ rows.append({
117
+ "ticketId": ticket.get("ticketId", "-"),
118
+ "user": info.get("user", "-"),
119
+ "productName": (info.get("productName", "") or "-")[:30],
120
+ "token": (info.get("token", "") or "-")[:25],
121
+ "status": decision.get("status", "-"),
122
+ "createdOn": (info.get("createdOn", "") or "-")[:19],
123
+ })
124
+ columns = [
125
+ ("Ticket", "ticketId"),
126
+ ("User", "user"),
127
+ ("Application", "productName"),
128
+ ("Token Requested", "token"),
129
+ ("Status", "status"),
130
+ ("Created", "createdOn"),
131
+ ]
132
+ print_table(rows, columns, title="JIT App Authorization Requests")
133
+ except httpx.HTTPStatusError as e:
134
+ print_api_error(e, "list authorization requests")
135
+ raise typer.Exit(1)
136
+ except httpx.RequestError as e:
137
+ print_api_error(e, "list authorization requests")
138
+ raise typer.Exit(1)
139
+ except Exception as e:
140
+ print_api_error(e, "list authorization requests")
141
+ raise typer.Exit(1)
142
+
143
+
144
+ @authorization_app.command("get")
145
+ def get_authorization_request(
146
+ request_id: str = typer.Argument(..., help="Request ID (ticket ID like EPM000001)"),
147
+ output: OutputFormat = typer.Option(
148
+ OutputFormat.JSON, "--output", "-o", help="Output format"
149
+ ),
150
+ ):
151
+ """Get authorization request details."""
152
+ from bt_cli.epmw.client import get_client
153
+
154
+ try:
155
+ client = get_client()
156
+ request = client.get_authorization_request(request_id)
157
+
158
+ if output == OutputFormat.JSON:
159
+ print_json(request)
160
+ else:
161
+ info = request.get("requestInfo", {})
162
+ decision = request.get("accessDecision", {})
163
+ ticket = request.get("serviceTicket", {})
164
+
165
+ typer.echo(f"Ticket ID: {ticket.get('ticketId', '-')}")
166
+ typer.echo(f"User: {info.get('user', '-')}")
167
+ typer.echo(f"Application: {info.get('productName', '-')}")
168
+ typer.echo(f"Application Type: {info.get('applicationType', '-')}")
169
+ typer.echo(f"Token: {info.get('token', '-')}")
170
+ typer.echo(f"Reason: {info.get('reason', '-')}")
171
+ typer.echo(f"Status: {decision.get('status', '-')}")
172
+ typer.echo(f"Duration: {decision.get('duration', '-')}")
173
+ typer.echo(f"Start Time: {decision.get('startTime', '-')}")
174
+ typer.echo(f"Created: {info.get('createdOn', '-')}")
175
+ typer.echo(f"Modified: {info.get('modifiedOn', '-')}")
176
+ except httpx.HTTPStatusError as e:
177
+ print_api_error(e, "get authorization request")
178
+ raise typer.Exit(1)
179
+ except httpx.RequestError as e:
180
+ print_api_error(e, "get authorization request")
181
+ raise typer.Exit(1)
182
+ except Exception as e:
183
+ print_api_error(e, "get authorization request")
184
+ raise typer.Exit(1)
185
+
186
+
187
+ # Authorization request audits
188
+ @requests_app.command("list")
189
+ def list_authorization_request_audits(
190
+ output: OutputFormat = typer.Option(
191
+ OutputFormat.TABLE, "--output", "-o", help="Output format"
192
+ ),
193
+ ):
194
+ """List authorization request audit records."""
195
+ from bt_cli.epmw.client import get_client
196
+
197
+ try:
198
+ client = get_client()
199
+ audits = client.list_authorization_request_audits()
200
+
201
+ if output == OutputFormat.JSON:
202
+ print_json(audits)
203
+ else:
204
+ columns = [
205
+ ("ID", "id"),
206
+ ("Computer", "computerName"),
207
+ ("User", "userName"),
208
+ ("Action", "action"),
209
+ ("Created", "created"),
210
+ ]
211
+ print_table(audits, columns, title="Authorization Request Audits")
212
+ except httpx.HTTPStatusError as e:
213
+ print_api_error(e, "list authorization request audits")
214
+ raise typer.Exit(1)
215
+ except httpx.RequestError as e:
216
+ print_api_error(e, "list authorization request audits")
217
+ raise typer.Exit(1)
218
+ except Exception as e:
219
+ print_api_error(e, "list authorization request audits")
220
+ raise typer.Exit(1)
221
+
222
+
223
+ @requests_app.command("get")
224
+ def get_authorization_request_audit(
225
+ audit_id: str = typer.Argument(..., help="Audit ID"),
226
+ output: OutputFormat = typer.Option(
227
+ OutputFormat.JSON, "--output", "-o", help="Output format"
228
+ ),
229
+ ):
230
+ """Get authorization request audit details."""
231
+ from bt_cli.epmw.client import get_client
232
+
233
+ try:
234
+ client = get_client()
235
+ audit = client.get_authorization_request_audit(audit_id)
236
+
237
+ if output == OutputFormat.JSON:
238
+ print_json(audit)
239
+ else:
240
+ for key, value in audit.items():
241
+ typer.echo(f"{key}: {value}")
242
+ except httpx.HTTPStatusError as e:
243
+ print_api_error(e, "get authorization request audit")
244
+ raise typer.Exit(1)
245
+ except httpx.RequestError as e:
246
+ print_api_error(e, "get authorization request audit")
247
+ raise typer.Exit(1)
248
+ except Exception as e:
249
+ print_api_error(e, "get authorization request audit")
250
+ raise typer.Exit(1)
@@ -0,0 +1,55 @@
1
+ """EPMW authentication commands."""
2
+
3
+ import os
4
+
5
+ import httpx
6
+ import typer
7
+
8
+ from bt_cli.core.output import print_error, print_success, print_warning, print_api_error
9
+
10
+ app = typer.Typer(no_args_is_help=True, help="Authentication and connection testing")
11
+
12
+
13
+ @app.command()
14
+ def test():
15
+ """Test EPM Windows API connection."""
16
+ from bt_cli.epmw.client import get_client
17
+
18
+ try:
19
+ client = get_client()
20
+ # Try to list computers as a connection test
21
+ computers = client.list_computers()
22
+ print_success("Connected to EPM Windows API")
23
+ print_success(f"Found {len(computers)} computers")
24
+ except ValueError as e:
25
+ print_error(f"Configuration error: {e}")
26
+ raise typer.Exit(1)
27
+ except httpx.HTTPStatusError as e:
28
+ print_api_error(e, "test connection")
29
+ raise typer.Exit(1)
30
+ except httpx.RequestError as e:
31
+ print_api_error(e, "test connection")
32
+ raise typer.Exit(1)
33
+ except Exception as e:
34
+ print_api_error(e, "test connection")
35
+ raise typer.Exit(1)
36
+
37
+
38
+ @app.command()
39
+ def status():
40
+ """Show EPM Windows configuration status."""
41
+ api_url = os.getenv("BT_EPM_API_URL", "")
42
+ client_id = os.getenv("BT_EPM_CLIENT_ID", "")
43
+ client_secret = os.getenv("BT_EPM_CLIENT_SECRET", "")
44
+
45
+ typer.echo("EPM Windows Configuration:")
46
+ typer.echo(f" API URL: {api_url or '(not set)'}")
47
+ typer.echo(f" Client ID: {client_id[:8] + '...' if client_id else '(not set)'}")
48
+ typer.echo(f" Client Secret: {'*' * 8 if client_secret else '(not set)'}")
49
+
50
+ if not api_url:
51
+ print_warning("BT_EPM_API_URL is not set")
52
+ if not client_id:
53
+ print_warning("BT_EPM_CLIENT_ID is not set")
54
+ if not client_secret:
55
+ print_warning("BT_EPM_CLIENT_SECRET is not set")
@@ -0,0 +1,140 @@
1
+ """EPMW computers commands."""
2
+
3
+ import httpx
4
+ import typer
5
+
6
+ from bt_cli.core.output import OutputFormat, print_api_error, print_json, print_table
7
+
8
+ app = typer.Typer(no_args_is_help=True, help="Managed endpoint computers")
9
+
10
+
11
+ @app.command("list")
12
+ def list_computers(
13
+ output: OutputFormat = typer.Option(
14
+ OutputFormat.TABLE, "--output", "-o", help="Output format"
15
+ ),
16
+ ):
17
+ """List all computers."""
18
+ from bt_cli.epmw.client import get_client
19
+
20
+ try:
21
+ client = get_client()
22
+ computers = client.list_computers()
23
+
24
+ if output == OutputFormat.JSON:
25
+ print_json(computers)
26
+ else:
27
+ columns = [
28
+ ("ID", "id"),
29
+ ("Host", "host"),
30
+ ("Domain", "domain"),
31
+ ("Group", "groupName"),
32
+ ("Status", "connectionStatus"),
33
+ ("OS", "os"),
34
+ ]
35
+ print_table(computers, columns, title="Computers")
36
+ except httpx.HTTPStatusError as e:
37
+ print_api_error(e, "list computers")
38
+ raise typer.Exit(1)
39
+ except httpx.RequestError as e:
40
+ print_api_error(e, "list computers")
41
+ raise typer.Exit(1)
42
+ except Exception as e:
43
+ print_api_error(e, "list computers")
44
+ raise typer.Exit(1)
45
+
46
+
47
+ @app.command("get")
48
+ def get_computer(
49
+ computer_id: str = typer.Argument(..., help="Computer ID"),
50
+ output: OutputFormat = typer.Option(
51
+ OutputFormat.JSON, "--output", "-o", help="Output format"
52
+ ),
53
+ ):
54
+ """Get computer details."""
55
+ from bt_cli.epmw.client import get_client
56
+
57
+ try:
58
+ client = get_client()
59
+ computer = client.get_computer(computer_id)
60
+
61
+ if output == OutputFormat.JSON:
62
+ print_json(computer)
63
+ else:
64
+ for key, value in computer.items():
65
+ typer.echo(f"{key}: {value}")
66
+ except httpx.HTTPStatusError as e:
67
+ print_api_error(e, "get computer")
68
+ raise typer.Exit(1)
69
+ except httpx.RequestError as e:
70
+ print_api_error(e, "get computer")
71
+ raise typer.Exit(1)
72
+ except Exception as e:
73
+ print_api_error(e, "get computer")
74
+ raise typer.Exit(1)
75
+
76
+
77
+ @app.command("delete")
78
+ def delete_computer(
79
+ computer_id: str = typer.Argument(..., help="Computer ID"),
80
+ ):
81
+ """Delete a computer."""
82
+ from bt_cli.epmw.client import get_client
83
+
84
+ try:
85
+ client = get_client()
86
+ client.delete_computer(computer_id)
87
+ typer.echo(f"Deleted computer: {computer_id}")
88
+ except httpx.HTTPStatusError as e:
89
+ print_api_error(e, "delete computer")
90
+ raise typer.Exit(1)
91
+ except httpx.RequestError as e:
92
+ print_api_error(e, "delete computer")
93
+ raise typer.Exit(1)
94
+ except Exception as e:
95
+ print_api_error(e, "delete computer")
96
+ raise typer.Exit(1)
97
+
98
+
99
+ @app.command("archive")
100
+ def archive_computer(
101
+ computer_id: str = typer.Argument(..., help="Computer ID"),
102
+ ):
103
+ """Archive a computer."""
104
+ from bt_cli.epmw.client import get_client
105
+
106
+ try:
107
+ client = get_client()
108
+ client.archive_computer(computer_id)
109
+ typer.echo(f"Archived computer: {computer_id}")
110
+ except httpx.HTTPStatusError as e:
111
+ print_api_error(e, "archive computer")
112
+ raise typer.Exit(1)
113
+ except httpx.RequestError as e:
114
+ print_api_error(e, "archive computer")
115
+ raise typer.Exit(1)
116
+ except Exception as e:
117
+ print_api_error(e, "archive computer")
118
+ raise typer.Exit(1)
119
+
120
+
121
+ @app.command("unarchive")
122
+ def unarchive_computer(
123
+ computer_id: str = typer.Argument(..., help="Computer ID"),
124
+ ):
125
+ """Unarchive a computer."""
126
+ from bt_cli.epmw.client import get_client
127
+
128
+ try:
129
+ client = get_client()
130
+ client.unarchive_computer(computer_id)
131
+ typer.echo(f"Unarchived computer: {computer_id}")
132
+ except httpx.HTTPStatusError as e:
133
+ print_api_error(e, "unarchive computer")
134
+ raise typer.Exit(1)
135
+ except httpx.RequestError as e:
136
+ print_api_error(e, "unarchive computer")
137
+ raise typer.Exit(1)
138
+ except Exception as e:
139
+ print_api_error(e, "unarchive computer")
140
+ raise typer.Exit(1)