aws-bootstrap-g4dn 0.1.0__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.
@@ -0,0 +1,528 @@
1
+ """Tests for CLI entry point and help output."""
2
+
3
+ from __future__ import annotations
4
+ from datetime import UTC, datetime
5
+ from pathlib import Path
6
+ from unittest.mock import patch
7
+
8
+ from click.testing import CliRunner
9
+
10
+ from aws_bootstrap.cli import main
11
+ from aws_bootstrap.ssh import GpuInfo, SSHHostDetails
12
+
13
+
14
+ def test_help():
15
+ runner = CliRunner()
16
+ result = runner.invoke(main, ["--help"])
17
+ assert result.exit_code == 0
18
+ assert "Bootstrap AWS EC2 GPU instances" in result.output
19
+ assert "launch" in result.output
20
+ assert "status" in result.output
21
+ assert "terminate" in result.output
22
+ assert "list" in result.output
23
+
24
+
25
+ def test_version():
26
+ runner = CliRunner()
27
+ result = runner.invoke(main, ["--version"])
28
+ assert result.exit_code == 0
29
+ assert "version" in result.output
30
+
31
+
32
+ def test_launch_help():
33
+ runner = CliRunner()
34
+ result = runner.invoke(main, ["launch", "--help"])
35
+ assert result.exit_code == 0
36
+ assert "--instance-type" in result.output
37
+ assert "--spot" in result.output
38
+ assert "--dry-run" in result.output
39
+ assert "--key-path" in result.output
40
+
41
+
42
+ def test_launch_missing_key():
43
+ runner = CliRunner()
44
+ result = runner.invoke(main, ["launch", "--key-path", "/nonexistent/key.pub"])
45
+ assert result.exit_code != 0
46
+ assert "SSH public key not found" in result.output
47
+
48
+
49
+ def test_status_help():
50
+ runner = CliRunner()
51
+ result = runner.invoke(main, ["status", "--help"])
52
+ assert result.exit_code == 0
53
+ assert "--region" in result.output
54
+ assert "--profile" in result.output
55
+
56
+
57
+ def test_terminate_help():
58
+ runner = CliRunner()
59
+ result = runner.invoke(main, ["terminate", "--help"])
60
+ assert result.exit_code == 0
61
+ assert "--region" in result.output
62
+ assert "--yes" in result.output
63
+
64
+
65
+ @patch("aws_bootstrap.cli.boto3.Session")
66
+ @patch("aws_bootstrap.cli.find_tagged_instances")
67
+ def test_status_no_instances(mock_find, mock_session):
68
+ mock_find.return_value = []
69
+ runner = CliRunner()
70
+ result = runner.invoke(main, ["status"])
71
+ assert result.exit_code == 0
72
+ assert "No active" in result.output
73
+
74
+
75
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
76
+ @patch("aws_bootstrap.cli.boto3.Session")
77
+ @patch("aws_bootstrap.cli.get_spot_price")
78
+ @patch("aws_bootstrap.cli.find_tagged_instances")
79
+ def test_status_shows_instances(mock_find, mock_spot_price, mock_session, mock_ssh_hosts):
80
+ mock_find.return_value = [
81
+ {
82
+ "InstanceId": "i-abc123",
83
+ "Name": "aws-bootstrap-g4dn.xlarge",
84
+ "State": "running",
85
+ "InstanceType": "g4dn.xlarge",
86
+ "PublicIp": "1.2.3.4",
87
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
88
+ "Lifecycle": "spot",
89
+ "AvailabilityZone": "us-west-2a",
90
+ }
91
+ ]
92
+ mock_spot_price.return_value = 0.1578
93
+ runner = CliRunner()
94
+ result = runner.invoke(main, ["status"])
95
+ assert result.exit_code == 0
96
+ assert "i-abc123" in result.output
97
+ assert "1.2.3.4" in result.output
98
+ assert "spot ($0.1578/hr)" in result.output
99
+ assert "Uptime" in result.output
100
+ assert "Est. cost" in result.output
101
+
102
+
103
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
104
+ @patch("aws_bootstrap.cli.boto3.Session")
105
+ @patch("aws_bootstrap.cli.get_spot_price")
106
+ @patch("aws_bootstrap.cli.find_tagged_instances")
107
+ def test_status_on_demand_no_cost(mock_find, mock_spot_price, mock_session, mock_ssh_hosts):
108
+ mock_find.return_value = [
109
+ {
110
+ "InstanceId": "i-ondemand",
111
+ "Name": "aws-bootstrap-g4dn.xlarge",
112
+ "State": "running",
113
+ "InstanceType": "g4dn.xlarge",
114
+ "PublicIp": "5.6.7.8",
115
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
116
+ "Lifecycle": "on-demand",
117
+ "AvailabilityZone": "us-west-2a",
118
+ }
119
+ ]
120
+ runner = CliRunner()
121
+ result = runner.invoke(main, ["status"])
122
+ assert result.exit_code == 0
123
+ assert "on-demand" in result.output
124
+ assert "Uptime" not in result.output
125
+ assert "Est. cost" not in result.output
126
+ mock_spot_price.assert_not_called()
127
+
128
+
129
+ @patch("aws_bootstrap.cli.boto3.Session")
130
+ @patch("aws_bootstrap.cli.find_tagged_instances")
131
+ def test_terminate_no_instances(mock_find, mock_session):
132
+ mock_find.return_value = []
133
+ runner = CliRunner()
134
+ result = runner.invoke(main, ["terminate"])
135
+ assert result.exit_code == 0
136
+ assert "No active" in result.output
137
+
138
+
139
+ @patch("aws_bootstrap.cli.remove_ssh_host", return_value=None)
140
+ @patch("aws_bootstrap.cli.boto3.Session")
141
+ @patch("aws_bootstrap.cli.find_tagged_instances")
142
+ @patch("aws_bootstrap.cli.terminate_tagged_instances")
143
+ def test_terminate_with_confirm(mock_terminate, mock_find, mock_session, mock_remove_ssh):
144
+ mock_find.return_value = [
145
+ {
146
+ "InstanceId": "i-abc123",
147
+ "Name": "test",
148
+ "State": "running",
149
+ "InstanceType": "g4dn.xlarge",
150
+ "PublicIp": "1.2.3.4",
151
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
152
+ }
153
+ ]
154
+ mock_terminate.return_value = [
155
+ {
156
+ "InstanceId": "i-abc123",
157
+ "PreviousState": {"Name": "running"},
158
+ "CurrentState": {"Name": "shutting-down"},
159
+ }
160
+ ]
161
+ runner = CliRunner()
162
+ result = runner.invoke(main, ["terminate", "--yes"])
163
+ assert result.exit_code == 0
164
+ assert "Terminated 1" in result.output
165
+ mock_terminate.assert_called_once()
166
+ assert mock_terminate.call_args[0][1] == ["i-abc123"]
167
+
168
+
169
+ @patch("aws_bootstrap.cli.boto3.Session")
170
+ @patch("aws_bootstrap.cli.find_tagged_instances")
171
+ def test_terminate_cancelled(mock_find, mock_session):
172
+ mock_find.return_value = [
173
+ {
174
+ "InstanceId": "i-abc123",
175
+ "Name": "test",
176
+ "State": "running",
177
+ "InstanceType": "g4dn.xlarge",
178
+ "PublicIp": "",
179
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
180
+ }
181
+ ]
182
+ runner = CliRunner()
183
+ result = runner.invoke(main, ["terminate"], input="n\n")
184
+ assert result.exit_code == 0
185
+ assert "Cancelled" in result.output
186
+
187
+
188
+ # ---------------------------------------------------------------------------
189
+ # list subcommand
190
+ # ---------------------------------------------------------------------------
191
+
192
+
193
+ def test_list_help():
194
+ runner = CliRunner()
195
+ result = runner.invoke(main, ["list", "--help"])
196
+ assert result.exit_code == 0
197
+ assert "instance-types" in result.output
198
+ assert "amis" in result.output
199
+
200
+
201
+ def test_list_instance_types_help():
202
+ runner = CliRunner()
203
+ result = runner.invoke(main, ["list", "instance-types", "--help"])
204
+ assert result.exit_code == 0
205
+ assert "--prefix" in result.output
206
+ assert "--region" in result.output
207
+
208
+
209
+ def test_list_amis_help():
210
+ runner = CliRunner()
211
+ result = runner.invoke(main, ["list", "amis", "--help"])
212
+ assert result.exit_code == 0
213
+ assert "--filter" in result.output
214
+ assert "--region" in result.output
215
+
216
+
217
+ @patch("aws_bootstrap.cli.boto3.Session")
218
+ @patch("aws_bootstrap.cli.list_instance_types")
219
+ def test_list_instance_types_output(mock_list, mock_session):
220
+ mock_list.return_value = [
221
+ {
222
+ "InstanceType": "g4dn.xlarge",
223
+ "VCpuCount": 4,
224
+ "MemoryMiB": 16384,
225
+ "GpuSummary": "1x T4 (16384 MiB)",
226
+ },
227
+ ]
228
+ runner = CliRunner()
229
+ result = runner.invoke(main, ["list", "instance-types"])
230
+ assert result.exit_code == 0
231
+ assert "g4dn.xlarge" in result.output
232
+ assert "16384" in result.output
233
+ assert "T4" in result.output
234
+
235
+
236
+ @patch("aws_bootstrap.cli.boto3.Session")
237
+ @patch("aws_bootstrap.cli.list_instance_types")
238
+ def test_list_instance_types_empty(mock_list, mock_session):
239
+ mock_list.return_value = []
240
+ runner = CliRunner()
241
+ result = runner.invoke(main, ["list", "instance-types", "--prefix", "zzz"])
242
+ assert result.exit_code == 0
243
+ assert "No instance types found" in result.output
244
+
245
+
246
+ @patch("aws_bootstrap.cli.boto3.Session")
247
+ @patch("aws_bootstrap.cli.list_amis")
248
+ def test_list_amis_output(mock_list, mock_session):
249
+ mock_list.return_value = [
250
+ {
251
+ "ImageId": "ami-abc123",
252
+ "Name": "Deep Learning AMI v42",
253
+ "CreationDate": "2025-06-01T00:00:00Z",
254
+ "Architecture": "x86_64",
255
+ },
256
+ ]
257
+ runner = CliRunner()
258
+ result = runner.invoke(main, ["list", "amis"])
259
+ assert result.exit_code == 0
260
+ assert "ami-abc123" in result.output
261
+ assert "Deep Learning AMI v42" in result.output
262
+ assert "2025-06-01" in result.output
263
+
264
+
265
+ @patch("aws_bootstrap.cli.boto3.Session")
266
+ @patch("aws_bootstrap.cli.list_amis")
267
+ def test_list_amis_empty(mock_list, mock_session):
268
+ mock_list.return_value = []
269
+ runner = CliRunner()
270
+ result = runner.invoke(main, ["list", "amis", "--filter", "nonexistent*"])
271
+ assert result.exit_code == 0
272
+ assert "No AMIs found" in result.output
273
+
274
+
275
+ # ---------------------------------------------------------------------------
276
+ # SSH config integration tests
277
+ # ---------------------------------------------------------------------------
278
+
279
+
280
+ @patch("aws_bootstrap.cli.add_ssh_host", return_value="aws-gpu1")
281
+ @patch("aws_bootstrap.cli.run_remote_setup", return_value=True)
282
+ @patch("aws_bootstrap.cli.wait_for_ssh", return_value=True)
283
+ @patch("aws_bootstrap.cli.wait_instance_ready")
284
+ @patch("aws_bootstrap.cli.launch_instance")
285
+ @patch("aws_bootstrap.cli.ensure_security_group", return_value="sg-123")
286
+ @patch("aws_bootstrap.cli.import_key_pair", return_value="aws-bootstrap-key")
287
+ @patch("aws_bootstrap.cli.get_latest_ami")
288
+ @patch("aws_bootstrap.cli.boto3.Session")
289
+ def test_launch_output_shows_ssh_alias(
290
+ mock_session, mock_ami, mock_import, mock_sg, mock_launch, mock_wait, mock_ssh, mock_setup, mock_add_ssh, tmp_path
291
+ ):
292
+ mock_ami.return_value = {"ImageId": "ami-123", "Name": "TestAMI"}
293
+ mock_launch.return_value = {"InstanceId": "i-test123"}
294
+ mock_wait.return_value = {"PublicIpAddress": "1.2.3.4"}
295
+
296
+ key_path = tmp_path / "id_ed25519.pub"
297
+ key_path.write_text("ssh-ed25519 AAAA test@host")
298
+
299
+ runner = CliRunner()
300
+ result = runner.invoke(main, ["launch", "--key-path", str(key_path), "--no-setup"])
301
+ assert result.exit_code == 0
302
+ assert "ssh aws-gpu1" in result.output
303
+ assert "SSH alias: aws-gpu1" in result.output
304
+ mock_add_ssh.assert_called_once()
305
+
306
+
307
+ @patch("aws_bootstrap.cli.boto3.Session")
308
+ @patch("aws_bootstrap.cli.get_latest_ami")
309
+ @patch("aws_bootstrap.cli.import_key_pair", return_value="aws-bootstrap-key")
310
+ @patch("aws_bootstrap.cli.ensure_security_group", return_value="sg-123")
311
+ @patch("aws_bootstrap.cli.add_ssh_host")
312
+ def test_launch_dry_run_no_ssh_config(mock_add_ssh, mock_sg, mock_import, mock_ami, mock_session, tmp_path):
313
+ mock_ami.return_value = {"ImageId": "ami-123", "Name": "TestAMI"}
314
+
315
+ key_path = tmp_path / "id_ed25519.pub"
316
+ key_path.write_text("ssh-ed25519 AAAA test@host")
317
+
318
+ runner = CliRunner()
319
+ result = runner.invoke(main, ["launch", "--key-path", str(key_path), "--dry-run"])
320
+ assert result.exit_code == 0
321
+ mock_add_ssh.assert_not_called()
322
+
323
+
324
+ @patch("aws_bootstrap.cli.remove_ssh_host", return_value="aws-gpu1")
325
+ @patch("aws_bootstrap.cli.boto3.Session")
326
+ @patch("aws_bootstrap.cli.find_tagged_instances")
327
+ @patch("aws_bootstrap.cli.terminate_tagged_instances")
328
+ def test_terminate_removes_ssh_config(mock_terminate, mock_find, mock_session, mock_remove_ssh):
329
+ mock_find.return_value = [
330
+ {
331
+ "InstanceId": "i-abc123",
332
+ "Name": "test",
333
+ "State": "running",
334
+ "InstanceType": "g4dn.xlarge",
335
+ "PublicIp": "1.2.3.4",
336
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
337
+ }
338
+ ]
339
+ mock_terminate.return_value = [
340
+ {
341
+ "InstanceId": "i-abc123",
342
+ "PreviousState": {"Name": "running"},
343
+ "CurrentState": {"Name": "shutting-down"},
344
+ }
345
+ ]
346
+ runner = CliRunner()
347
+ result = runner.invoke(main, ["terminate", "--yes"])
348
+ assert result.exit_code == 0
349
+ assert "Removed SSH config alias: aws-gpu1" in result.output
350
+ mock_remove_ssh.assert_called_once_with("i-abc123")
351
+
352
+
353
+ @patch("aws_bootstrap.cli.list_ssh_hosts")
354
+ @patch("aws_bootstrap.cli.boto3.Session")
355
+ @patch("aws_bootstrap.cli.get_spot_price")
356
+ @patch("aws_bootstrap.cli.find_tagged_instances")
357
+ def test_status_shows_alias(mock_find, mock_spot_price, mock_session, mock_ssh_hosts):
358
+ mock_find.return_value = [
359
+ {
360
+ "InstanceId": "i-abc123",
361
+ "Name": "aws-bootstrap-g4dn.xlarge",
362
+ "State": "running",
363
+ "InstanceType": "g4dn.xlarge",
364
+ "PublicIp": "1.2.3.4",
365
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
366
+ "Lifecycle": "spot",
367
+ "AvailabilityZone": "us-west-2a",
368
+ }
369
+ ]
370
+ mock_spot_price.return_value = 0.15
371
+ mock_ssh_hosts.return_value = {"i-abc123": "aws-gpu1"}
372
+ runner = CliRunner()
373
+ result = runner.invoke(main, ["status"])
374
+ assert result.exit_code == 0
375
+ assert "aws-gpu1" in result.output
376
+
377
+
378
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
379
+ @patch("aws_bootstrap.cli.boto3.Session")
380
+ @patch("aws_bootstrap.cli.get_spot_price")
381
+ @patch("aws_bootstrap.cli.find_tagged_instances")
382
+ def test_status_no_alias_graceful(mock_find, mock_spot_price, mock_session, mock_ssh_hosts):
383
+ mock_find.return_value = [
384
+ {
385
+ "InstanceId": "i-old999",
386
+ "Name": "aws-bootstrap-g4dn.xlarge",
387
+ "State": "running",
388
+ "InstanceType": "g4dn.xlarge",
389
+ "PublicIp": "9.8.7.6",
390
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
391
+ "Lifecycle": "spot",
392
+ "AvailabilityZone": "us-west-2a",
393
+ }
394
+ ]
395
+ mock_spot_price.return_value = 0.15
396
+ runner = CliRunner()
397
+ result = runner.invoke(main, ["status"])
398
+ assert result.exit_code == 0
399
+ assert "i-old999" in result.output
400
+
401
+
402
+ # ---------------------------------------------------------------------------
403
+ # --gpu flag tests
404
+ # ---------------------------------------------------------------------------
405
+
406
+ _RUNNING_INSTANCE = {
407
+ "InstanceId": "i-abc123",
408
+ "Name": "aws-bootstrap-g4dn.xlarge",
409
+ "State": "running",
410
+ "InstanceType": "g4dn.xlarge",
411
+ "PublicIp": "1.2.3.4",
412
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
413
+ "Lifecycle": "spot",
414
+ "AvailabilityZone": "us-west-2a",
415
+ }
416
+
417
+ _SAMPLE_GPU_INFO = GpuInfo(
418
+ driver_version="560.35.03",
419
+ cuda_driver_version="13.0",
420
+ cuda_toolkit_version="12.8",
421
+ gpu_name="Tesla T4",
422
+ compute_capability="7.5",
423
+ architecture="Turing",
424
+ )
425
+
426
+
427
+ def test_status_help_shows_gpu_flag():
428
+ runner = CliRunner()
429
+ result = runner.invoke(main, ["status", "--help"])
430
+ assert result.exit_code == 0
431
+ assert "--gpu" in result.output
432
+
433
+
434
+ @patch("aws_bootstrap.cli.query_gpu_info", return_value=_SAMPLE_GPU_INFO)
435
+ @patch("aws_bootstrap.cli.get_ssh_host_details")
436
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={"i-abc123": "aws-gpu1"})
437
+ @patch("aws_bootstrap.cli.boto3.Session")
438
+ @patch("aws_bootstrap.cli.get_spot_price", return_value=0.15)
439
+ @patch("aws_bootstrap.cli.find_tagged_instances")
440
+ def test_status_gpu_shows_info(mock_find, mock_spot, mock_session, mock_ssh_hosts, mock_details, mock_gpu):
441
+ mock_find.return_value = [_RUNNING_INSTANCE]
442
+ mock_details.return_value = SSHHostDetails(
443
+ hostname="1.2.3.4", user="ubuntu", identity_file=Path("/home/user/.ssh/id_ed25519")
444
+ )
445
+ runner = CliRunner()
446
+ result = runner.invoke(main, ["status", "--gpu"])
447
+ assert result.exit_code == 0
448
+ assert "Tesla T4 (Turing)" in result.output
449
+ assert "12.8" in result.output
450
+ assert "driver supports up to 13.0" in result.output
451
+ assert "560.35.03" in result.output
452
+ mock_gpu.assert_called_once()
453
+
454
+
455
+ @patch("aws_bootstrap.cli.query_gpu_info", return_value=None)
456
+ @patch("aws_bootstrap.cli.get_ssh_host_details")
457
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
458
+ @patch("aws_bootstrap.cli.boto3.Session")
459
+ @patch("aws_bootstrap.cli.get_spot_price", return_value=0.15)
460
+ @patch("aws_bootstrap.cli.find_tagged_instances")
461
+ def test_status_gpu_ssh_fails_gracefully(mock_find, mock_spot, mock_session, mock_ssh_hosts, mock_details, mock_gpu):
462
+ mock_find.return_value = [_RUNNING_INSTANCE]
463
+ mock_details.return_value = SSHHostDetails(
464
+ hostname="1.2.3.4", user="ubuntu", identity_file=Path("/home/user/.ssh/id_ed25519")
465
+ )
466
+ runner = CliRunner()
467
+ result = runner.invoke(main, ["status", "--gpu"])
468
+ assert result.exit_code == 0
469
+ assert "unavailable" in result.output
470
+
471
+
472
+ @patch("aws_bootstrap.cli.query_gpu_info", return_value=_SAMPLE_GPU_INFO)
473
+ @patch("aws_bootstrap.cli.get_ssh_host_details", return_value=None)
474
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
475
+ @patch("aws_bootstrap.cli.boto3.Session")
476
+ @patch("aws_bootstrap.cli.get_spot_price", return_value=0.15)
477
+ @patch("aws_bootstrap.cli.find_tagged_instances")
478
+ def test_status_gpu_no_ssh_config_uses_defaults(
479
+ mock_find, mock_spot, mock_session, mock_ssh_hosts, mock_details, mock_gpu
480
+ ):
481
+ mock_find.return_value = [_RUNNING_INSTANCE]
482
+ runner = CliRunner()
483
+ result = runner.invoke(main, ["status", "--gpu"])
484
+ assert result.exit_code == 0
485
+ # Should have been called with the instance IP and default user/key
486
+ mock_gpu.assert_called_once()
487
+ call_args = mock_gpu.call_args
488
+ assert call_args[0][0] == "1.2.3.4"
489
+ assert call_args[0][1] == "ubuntu"
490
+
491
+
492
+ @patch("aws_bootstrap.cli.query_gpu_info")
493
+ @patch("aws_bootstrap.cli.get_ssh_host_details")
494
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={})
495
+ @patch("aws_bootstrap.cli.boto3.Session")
496
+ @patch("aws_bootstrap.cli.find_tagged_instances")
497
+ def test_status_gpu_skips_non_running(mock_find, mock_session, mock_ssh_hosts, mock_details, mock_gpu):
498
+ mock_find.return_value = [
499
+ {
500
+ "InstanceId": "i-stopped",
501
+ "Name": "aws-bootstrap-g4dn.xlarge",
502
+ "State": "stopped",
503
+ "InstanceType": "g4dn.xlarge",
504
+ "PublicIp": "",
505
+ "LaunchTime": datetime(2025, 1, 1, tzinfo=UTC),
506
+ "Lifecycle": "on-demand",
507
+ "AvailabilityZone": "us-west-2a",
508
+ }
509
+ ]
510
+ runner = CliRunner()
511
+ result = runner.invoke(main, ["status", "--gpu"])
512
+ assert result.exit_code == 0
513
+ mock_gpu.assert_not_called()
514
+
515
+
516
+ @patch("aws_bootstrap.cli.query_gpu_info")
517
+ @patch("aws_bootstrap.cli.get_ssh_host_details")
518
+ @patch("aws_bootstrap.cli.list_ssh_hosts", return_value={"i-abc123": "aws-gpu1"})
519
+ @patch("aws_bootstrap.cli.boto3.Session")
520
+ @patch("aws_bootstrap.cli.get_spot_price", return_value=0.15)
521
+ @patch("aws_bootstrap.cli.find_tagged_instances")
522
+ def test_status_without_gpu_flag_no_ssh(mock_find, mock_spot, mock_session, mock_ssh_hosts, mock_details, mock_gpu):
523
+ mock_find.return_value = [_RUNNING_INSTANCE]
524
+ runner = CliRunner()
525
+ result = runner.invoke(main, ["status"])
526
+ assert result.exit_code == 0
527
+ mock_gpu.assert_not_called()
528
+ mock_details.assert_not_called()
@@ -0,0 +1,35 @@
1
+ """Tests for LaunchConfig defaults and overrides."""
2
+
3
+ from __future__ import annotations
4
+ from pathlib import Path
5
+
6
+ from aws_bootstrap.config import LaunchConfig
7
+
8
+
9
+ def test_defaults():
10
+ config = LaunchConfig()
11
+ assert config.instance_type == "g4dn.xlarge"
12
+ assert config.region == "us-west-2"
13
+ assert config.spot is True
14
+ assert config.volume_size == 100
15
+ assert config.ssh_user == "ubuntu"
16
+ assert config.key_name == "aws-bootstrap-key"
17
+ assert config.security_group == "aws-bootstrap-ssh"
18
+ assert config.tag_value == "aws-bootstrap-g4dn"
19
+ assert config.run_setup is True
20
+ assert config.dry_run is False
21
+
22
+
23
+ def test_overrides():
24
+ config = LaunchConfig(
25
+ instance_type="g5.xlarge",
26
+ region="us-east-1",
27
+ spot=False,
28
+ volume_size=200,
29
+ key_path=Path("/tmp/test.pub"),
30
+ )
31
+ assert config.instance_type == "g5.xlarge"
32
+ assert config.region == "us-east-1"
33
+ assert config.spot is False
34
+ assert config.volume_size == 200
35
+ assert config.key_path == Path("/tmp/test.pub")