nextmv 1.0.0.dev3__py3-none-any.whl → 1.0.0.dev4__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 (115) hide show
  1. nextmv/__about__.py +1 -1
  2. nextmv/cli/CONTRIBUTING.md +81 -29
  3. nextmv/cli/cloud/acceptance/create.py +20 -22
  4. nextmv/cli/cloud/acceptance/delete.py +7 -8
  5. nextmv/cli/cloud/acceptance/get.py +9 -10
  6. nextmv/cli/cloud/acceptance/list.py +3 -3
  7. nextmv/cli/cloud/acceptance/update.py +6 -6
  8. nextmv/cli/cloud/account/__init__.py +3 -3
  9. nextmv/cli/cloud/account/create.py +11 -11
  10. nextmv/cli/cloud/account/delete.py +6 -7
  11. nextmv/cli/cloud/account/get.py +3 -3
  12. nextmv/cli/cloud/account/update.py +5 -5
  13. nextmv/cli/cloud/app/create.py +25 -26
  14. nextmv/cli/cloud/app/delete.py +5 -6
  15. nextmv/cli/cloud/app/exists.py +2 -2
  16. nextmv/cli/cloud/app/get.py +2 -2
  17. nextmv/cli/cloud/app/list.py +3 -3
  18. nextmv/cli/cloud/app/push.py +269 -45
  19. nextmv/cli/cloud/app/update.py +12 -12
  20. nextmv/cli/cloud/batch/create.py +26 -28
  21. nextmv/cli/cloud/batch/delete.py +5 -6
  22. nextmv/cli/cloud/batch/get.py +8 -8
  23. nextmv/cli/cloud/batch/list.py +3 -3
  24. nextmv/cli/cloud/batch/metadata.py +4 -4
  25. nextmv/cli/cloud/batch/update.py +6 -6
  26. nextmv/cli/cloud/data/__init__.py +1 -1
  27. nextmv/cli/cloud/data/upload.py +15 -15
  28. nextmv/cli/cloud/ensemble/__init__.py +2 -0
  29. nextmv/cli/cloud/ensemble/create.py +21 -22
  30. nextmv/cli/cloud/ensemble/delete.py +5 -6
  31. nextmv/cli/cloud/ensemble/get.py +4 -4
  32. nextmv/cli/cloud/ensemble/list.py +63 -0
  33. nextmv/cli/cloud/ensemble/update.py +9 -9
  34. nextmv/cli/cloud/input_set/create.py +20 -22
  35. nextmv/cli/cloud/input_set/get.py +3 -3
  36. nextmv/cli/cloud/input_set/list.py +3 -3
  37. nextmv/cli/cloud/input_set/update.py +24 -24
  38. nextmv/cli/cloud/instance/create.py +14 -15
  39. nextmv/cli/cloud/instance/delete.py +5 -6
  40. nextmv/cli/cloud/instance/exists.py +2 -2
  41. nextmv/cli/cloud/instance/get.py +2 -2
  42. nextmv/cli/cloud/instance/list.py +3 -3
  43. nextmv/cli/cloud/instance/update.py +14 -14
  44. nextmv/cli/cloud/managed_input/create.py +14 -16
  45. nextmv/cli/cloud/managed_input/delete.py +6 -7
  46. nextmv/cli/cloud/managed_input/get.py +3 -3
  47. nextmv/cli/cloud/managed_input/list.py +3 -3
  48. nextmv/cli/cloud/managed_input/update.py +9 -9
  49. nextmv/cli/cloud/run/cancel.py +2 -2
  50. nextmv/cli/cloud/run/create.py +32 -33
  51. nextmv/cli/cloud/run/get.py +8 -8
  52. nextmv/cli/cloud/run/input.py +4 -4
  53. nextmv/cli/cloud/run/list.py +6 -6
  54. nextmv/cli/cloud/run/logs.py +9 -10
  55. nextmv/cli/cloud/run/metadata.py +4 -4
  56. nextmv/cli/cloud/run/track.py +32 -33
  57. nextmv/cli/cloud/scenario/create.py +21 -21
  58. nextmv/cli/cloud/scenario/delete.py +5 -6
  59. nextmv/cli/cloud/scenario/get.py +8 -8
  60. nextmv/cli/cloud/scenario/list.py +3 -3
  61. nextmv/cli/cloud/scenario/metadata.py +4 -4
  62. nextmv/cli/cloud/scenario/update.py +6 -6
  63. nextmv/cli/cloud/secrets/create.py +17 -17
  64. nextmv/cli/cloud/secrets/delete.py +5 -6
  65. nextmv/cli/cloud/secrets/get.py +4 -4
  66. nextmv/cli/cloud/secrets/list.py +3 -3
  67. nextmv/cli/cloud/secrets/update.py +17 -20
  68. nextmv/cli/cloud/shadow/create.py +31 -31
  69. nextmv/cli/cloud/shadow/delete.py +5 -6
  70. nextmv/cli/cloud/shadow/get.py +2 -2
  71. nextmv/cli/cloud/shadow/list.py +3 -3
  72. nextmv/cli/cloud/shadow/metadata.py +4 -4
  73. nextmv/cli/cloud/shadow/start.py +3 -3
  74. nextmv/cli/cloud/shadow/stop.py +4 -6
  75. nextmv/cli/cloud/shadow/update.py +6 -6
  76. nextmv/cli/cloud/switchback/create.py +19 -15
  77. nextmv/cli/cloud/switchback/delete.py +5 -6
  78. nextmv/cli/cloud/switchback/get.py +3 -3
  79. nextmv/cli/cloud/switchback/list.py +3 -3
  80. nextmv/cli/cloud/switchback/metadata.py +6 -6
  81. nextmv/cli/cloud/switchback/start.py +4 -4
  82. nextmv/cli/cloud/switchback/stop.py +4 -6
  83. nextmv/cli/cloud/switchback/update.py +6 -6
  84. nextmv/cli/cloud/upload/create.py +2 -2
  85. nextmv/cli/cloud/version/create.py +9 -10
  86. nextmv/cli/cloud/version/delete.py +5 -6
  87. nextmv/cli/cloud/version/exists.py +2 -2
  88. nextmv/cli/cloud/version/get.py +2 -2
  89. nextmv/cli/cloud/version/list.py +3 -3
  90. nextmv/cli/cloud/version/update.py +8 -8
  91. nextmv/cli/community/clone.py +12 -10
  92. nextmv/cli/community/list.py +9 -9
  93. nextmv/cli/configuration/config.py +43 -10
  94. nextmv/cli/configuration/create.py +3 -3
  95. nextmv/cli/configuration/delete.py +7 -7
  96. nextmv/cli/configuration/list.py +3 -3
  97. nextmv/cli/confirm.py +32 -0
  98. nextmv/cli/main.py +27 -36
  99. nextmv/cli/message.py +2 -2
  100. nextmv/cli/version.py +1 -1
  101. nextmv/cloud/application/__init__.py +190 -54
  102. nextmv/cloud/application/_batch_scenario.py +2 -2
  103. nextmv/cloud/application/_instance.py +2 -2
  104. nextmv/cloud/application/_managed_input.py +1 -1
  105. nextmv/cloud/application/_shadow.py +1 -1
  106. nextmv/cloud/application/_switchback.py +11 -3
  107. nextmv/cloud/application/_version.py +3 -2
  108. nextmv/cloud/shadow.py +43 -4
  109. nextmv/cloud/switchback.py +46 -9
  110. {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev4.dist-info}/METADATA +1 -1
  111. nextmv-1.0.0.dev4.dist-info/RECORD +183 -0
  112. nextmv-1.0.0.dev3.dist-info/RECORD +0 -181
  113. {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev4.dist-info}/WHEEL +0 -0
  114. {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev4.dist-info}/entry_points.txt +0 -0
  115. {nextmv-1.0.0.dev3.dist-info → nextmv-1.0.0.dev4.dist-info}/licenses/LICENSE +0 -0
@@ -21,17 +21,15 @@ def stop(
21
21
  """
22
22
  Stops a Nextmv Cloud shadow test.
23
23
 
24
- Before stopping a shadow test, it must be in a started state. You may
25
- use the [code]nextmv cloud shadow start[/code] command to start
26
- a shadow test. Alternatively, define a [code]--start-time[/code] when using
27
- the [code]nextmv cloud shadow create[/code] command to have the shadow test
28
- start automatically at a specific time.
24
+ Before stopping a shadow test, it must be in a started state. Experiments
25
+ in a [magenta]draft[/magenta] state, that haven't started, can be deleted
26
+ with the [code]nextmv cloud shadow delete[/code] command.
29
27
 
30
28
  [bold][underline]Examples[/underline][/bold]
31
29
 
32
30
  - Stop the shadow test with the ID [magenta]hop-analysis[/magenta] from application
33
31
  [magenta]hare-app[/magenta].
34
- $ [green]nextmv cloud shadow stop --app-id hare-app --shadow-test-id hop-analysis[/green]
32
+ $ [dim]nextmv cloud shadow stop --app-id hare-app --shadow-test-id hop-analysis[/dim]
35
33
  """
36
34
 
37
35
  in_progress(msg="Stopping shadow test...")
@@ -57,17 +57,17 @@ def update(
57
57
  [bold][underline]Examples[/underline][/bold]
58
58
 
59
59
  - Update the name of a shadow test.
60
- $ [green]nextmv cloud shadow update --app-id hare-app --shadow-test-id carrot-feast \\
61
- --name "Spring Carrot Harvest"[/green]
60
+ $ [dim]nextmv cloud shadow update --app-id hare-app --shadow-test-id carrot-feast \\
61
+ --name "Spring Carrot Harvest"[/dim]
62
62
 
63
63
  - Update the description of a shadow test.
64
- $ [green]nextmv cloud shadow update --app-id hare-app --shadow-test-id bunny-hop-routes \\
65
- --description "Optimizing hop paths through the meadow"[/green]
64
+ $ [dim]nextmv cloud shadow update --app-id hare-app --shadow-test-id bunny-hop-routes \\
65
+ --description "Optimizing hop paths through the meadow"[/dim]
66
66
 
67
67
  - Update both name and description and save the result.
68
- $ [green]nextmv cloud shadow update --app-id hare-app --shadow-test-id lettuce-delivery \\
68
+ $ [dim]nextmv cloud shadow update --app-id hare-app --shadow-test-id lettuce-delivery \\
69
69
  --name "Warren Lettuce Express" --description "Fast lettuce delivery to all burrows" \\
70
- --output updated-shadow-test.json[/green]
70
+ --output updated-shadow-test.json[/dim]
71
71
  """
72
72
 
73
73
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -44,6 +44,8 @@ def create(
44
44
  "-u",
45
45
  help="Duration of each interval in minutes.",
46
46
  metavar="UNIT_DURATION_MINUTES",
47
+ min=1,
48
+ max=10080,
47
49
  ),
48
50
  ],
49
51
  units: Annotated[
@@ -53,6 +55,8 @@ def create(
53
55
  "-t",
54
56
  help="Total number of intervals in the switchback test.",
55
57
  metavar="UNITS",
58
+ min=1,
59
+ max=1000,
56
60
  ),
57
61
  ],
58
62
  description: Annotated[
@@ -90,7 +94,7 @@ def create(
90
94
  "-r",
91
95
  formats=["%Y-%m-%dT%H:%M:%S%z"],
92
96
  help="Scheduled time for switchback test start in [magenta]RFC 3339[/magenta] format. "
93
- "Example: [magenta]'2024-01-01T00:00:00Z'[/magenta]",
97
+ "Object format: [dim]'2024-01-01T00:00:00Z'[/dim]",
94
98
  metavar="START",
95
99
  ),
96
100
  ] = None,
@@ -99,33 +103,33 @@ def create(
99
103
  """
100
104
  Create a new Nextmv Cloud switchback test in draft mode.
101
105
 
102
- The test will alternate between the [code]--baseline-instance-id[/code] and
103
- [code]--candidate-instance-id[/code] over specified time intervals.
106
+ The test will alternate between the --baseline-instance-id and
107
+ --candidate-instance-id over specified time intervals.
104
108
 
105
- You may specify the [code]--start[/code] option to make the switchback
106
- test start at a specific time. Alternatively, you may use the
107
- [code]nextmv cloud switchback start[/code] command to start the test.
109
+ You may specify the --start option to make the switchback test start at a
110
+ specific time. Alternatively, you may use the [code]nextmv cloud switchback
111
+ start[/code] command to start the test.
108
112
 
109
113
  Use the [code]nextmv cloud switchback stop[/code] command to stop the test.
110
114
 
111
115
  [bold][underline]Examples[/underline][/bold]
112
116
 
113
- - Create a switchback test alternating between two bunny instances:
114
- $ [green]nextmv cloud switchback create --app-id hare-app --switchback-test-id bunny-switch-hop \\
117
+ - Create a switchback test alternating between two bunny instances.
118
+ $ [dim]nextmv cloud switchback create --app-id hare-app --switchback-test-id bunny-switch-hop \\
115
119
  --name "Bunny Switch Hop" --baseline-instance-id fluffy-bunny-baseline \\
116
- --candidate-instance-id speedy-cottontail --unit-duration-minutes 15 --units 10[/green]
120
+ --candidate-instance-id speedy-cottontail --unit-duration-minutes 15 --units 10[/dim]
117
121
 
118
- - Create a switchback test with a scheduled start time:
119
- $ [green]nextmv cloud switchback create --app-id hare-app --switchback-test-id sunrise-switch \\
122
+ - Create a switchback test with a scheduled start time.
123
+ $ [dim]nextmv cloud switchback create --app-id hare-app --switchback-test-id sunrise-switch \\
120
124
  --name "Sunrise Switch Test" --baseline-instance-id wise-old-rabbit \\
121
125
  --candidate-instance-id burrow-master --unit-duration-minutes 30 --units 8 \\
122
- --start '2026-01-23T10:00:00Z'[/green]
126
+ --start '2026-01-23T10:00:00Z'[/dim]
123
127
 
124
- - Create a switchback test with a description:
125
- $ [green]nextmv cloud switchback create --app-id hare-app --switchback-test-id carrot-switch \\
128
+ - Create a switchback test with a description.
129
+ $ [dim]nextmv cloud switchback create --app-id hare-app --switchback-test-id carrot-switch \\
126
130
  --name "Carrot Switch" --baseline-instance-id fluffy-bunny-baseline \\
127
131
  --candidate-instance-id hopping-candidate-ears --unit-duration-minutes 20 --units 12 \\
128
- --description "Which bunny hops best for carrots?"[/green]
132
+ --description "Which bunny hops best for carrots?"[/dim]
129
133
  """
130
134
 
131
135
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -5,9 +5,9 @@ This module defines the cloud switchback delete command for the Nextmv CLI.
5
5
  from typing import Annotated
6
6
 
7
7
  import typer
8
- from rich.prompt import Confirm
9
8
 
10
9
  from nextmv.cli.configuration.config import build_app
10
+ from nextmv.cli.confirm import get_confirmation
11
11
  from nextmv.cli.message import info, success
12
12
  from nextmv.cli.options import AppIDOption, ProfileOption, SwitchbackTestIDOption
13
13
 
@@ -33,24 +33,23 @@ def delete(
33
33
  Deletes a Nextmv Cloud switchback test.
34
34
 
35
35
  This action is permanent and cannot be undone. The switchback test and all
36
- associated data, including runs, will be deleted. Use the [code]--yes[/code]
36
+ associated data, including runs, will be deleted. Use the --yes
37
37
  flag to skip the confirmation prompt.
38
38
 
39
39
  [bold][underline]Examples[/underline][/bold]
40
40
 
41
41
  - Delete the switchback test with the ID [magenta]hop-analysis[/magenta] from application
42
42
  [magenta]hare-app[/magenta].
43
- $ [green]nextmv cloud switchback delete --app-id hare-app --switchback-test-id hop-analysis[/green]
43
+ $ [dim]nextmv cloud switchback delete --app-id hare-app --switchback-test-id hop-analysis[/dim]
44
44
 
45
45
  - Delete the switchback test without confirmation prompt.
46
- $ [green]nextmv cloud switchback delete --app-id hare-app --switchback-test-id carrot-routes --yes[/green]
46
+ $ [dim]nextmv cloud switchback delete --app-id hare-app --switchback-test-id carrot-routes --yes[/dim]
47
47
  """
48
48
 
49
49
  if not yes:
50
- confirm = Confirm.ask(
50
+ confirm = get_confirmation(
51
51
  f"Are you sure you want to delete switchback test [magenta]{switchback_test_id}[/magenta] "
52
52
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
- default=False,
54
53
  )
55
54
 
56
55
  if not confirm:
@@ -37,11 +37,11 @@ def get(
37
37
 
38
38
  - Get the switchback test with ID [magenta]carrot-optimization[/magenta] from application
39
39
  [magenta]hare-app[/magenta].
40
- $ [green]nextmv cloud switchback get --app-id hare-app --switchback-test-id carrot-optimization[/green]
40
+ $ [dim]nextmv cloud switchback get --app-id hare-app --switchback-test-id carrot-optimization[/dim]
41
41
 
42
42
  - Get the switchback test using a specific profile.
43
- $ [green]nextmv cloud switchback get --app-id hare-app --switchback-test-id lettuce-routes \\
44
- --profile prod[/green]
43
+ $ [dim]nextmv cloud switchback get --app-id hare-app --switchback-test-id lettuce-routes \\
44
+ --profile prod[/dim]
45
45
  """
46
46
 
47
47
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -38,13 +38,13 @@ def list(
38
38
  [bold][underline]Examples[/underline][/bold]
39
39
 
40
40
  - List all switchback tests for application [magenta]hare-app[/magenta].
41
- $ [green]nextmv cloud switchback list --app-id hare-app[/green]
41
+ $ [dim]nextmv cloud switchback list --app-id hare-app[/dim]
42
42
 
43
43
  - List all switchback tests and save to a file.
44
- $ [green]nextmv cloud switchback list --app-id hare-app --output tests.json[/green]
44
+ $ [dim]nextmv cloud switchback list --app-id hare-app --output tests.json[/dim]
45
45
 
46
46
  - List all switchback tests using a specific profile.
47
- $ [green]nextmv cloud switchback list --app-id hare-app --profile prod[/green]
47
+ $ [dim]nextmv cloud switchback list --app-id hare-app --profile prod[/dim]
48
48
  """
49
49
 
50
50
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -41,16 +41,16 @@ def metadata(
41
41
 
42
42
  - Get metadata for switchback test [magenta]bunny-warren-optimization[/magenta] from application
43
43
  [magenta]hare-app[/magenta].
44
- $ [green]nextmv cloud switchback metadata --app-id hare-app \\
45
- --switchback-test-id bunny-warren-optimization[/green]
44
+ $ [dim]nextmv cloud switchback metadata --app-id hare-app \\
45
+ --switchback-test-id bunny-warren-optimization[/dim]
46
46
 
47
47
  - Get metadata and save to a file.
48
- $ [green]nextmv cloud switchback metadata --app-id hare-app --switchback-test-id lettuce-delivery \\
49
- --output metadata.json[/green]
48
+ $ [dim]nextmv cloud switchback metadata --app-id hare-app --switchback-test-id lettuce-delivery \\
49
+ --output metadata.json[/dim]
50
50
 
51
51
  - Get metadata using a specific profile.
52
- $ [green]nextmv cloud switchback metadata --app-id hare-app --switchback-test-id hop-schedule \\
53
- --profile prod[/green]
52
+ $ [dim]nextmv cloud switchback metadata --app-id hare-app --switchback-test-id hop-schedule \\
53
+ --profile prod[/dim]
54
54
  """
55
55
 
56
56
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -23,15 +23,15 @@ def start(
23
23
 
24
24
  Before starting a switchback test, it must be created in draft state. You
25
25
  may use the [code]nextmv cloud switchback create[/code] command to create a
26
- new switchback test. Alternatively, define a [code]--start[/code] when
27
- using the [code]nextmv cloud switchback create[/code] command to have the
28
- switchback test start automatically at a specific time.
26
+ new switchback test. Alternatively, define a --start when using the
27
+ [code]nextmv cloud switchback create[/code] command to have the switchback
28
+ test start automatically at a specific time.
29
29
 
30
30
  [bold][underline]Examples[/underline][/bold]
31
31
 
32
32
  - Start the switchback test with the ID [magenta]hop-analysis[/magenta] from application
33
33
  [magenta]hare-app[/magenta].
34
- $ [green]nextmv cloud switchback start --app-id hare-app --switchback-test-id hop-analysis[/green]
34
+ $ [dim]nextmv cloud switchback start --app-id hare-app --switchback-test-id hop-analysis[/dim]
35
35
  """
36
36
 
37
37
  in_progress(msg="Starting switchback test...")
@@ -21,17 +21,15 @@ def stop(
21
21
  """
22
22
  Stops a Nextmv Cloud switchback test.
23
23
 
24
- Before stopping a switchback test, it must be in a started state. You may
25
- use the [code]nextmv cloud switchback start[/code] command to start a
26
- switchback test. Alternatively, define a [code]--start[/code] when using
27
- the [code]nextmv cloud switchback create[/code] command to have the
28
- switchback test start automatically at a specific time.
24
+ Before stopping a switchback test, it must be in a started state. Experiments
25
+ in a [magenta]draft[/magenta] state, that haven't started, can be deleted
26
+ with the [code]nextmv cloud switchback delete[/code] command.
29
27
 
30
28
  [bold][underline]Examples[/underline][/bold]
31
29
 
32
30
  - Stop the switchback test with the ID [magenta]hop-analysis[/magenta] from application
33
31
  [magenta]hare-app[/magenta].
34
- $ [green]nextmv cloud switchback stop --app-id hare-app --switchback-test-id hop-analysis[/green]
32
+ $ [dim]nextmv cloud switchback stop --app-id hare-app --switchback-test-id hop-analysis[/dim]
35
33
  """
36
34
 
37
35
  in_progress(msg="Stopping switchback test...")
@@ -57,17 +57,17 @@ def update(
57
57
  [bold][underline]Examples[/underline][/bold]
58
58
 
59
59
  - Update the name of a switchback test.
60
- $ [green]nextmv cloud switchback update --app-id hare-app --switchback-test-id carrot-feast \\
61
- --name "Spring Carrot Harvest"[/green]
60
+ $ [dim]nextmv cloud switchback update --app-id hare-app --switchback-test-id carrot-feast \\
61
+ --name "Spring Carrot Harvest"[/dim]
62
62
 
63
63
  - Update the description of a switchback test.
64
- $ [green]nextmv cloud switchback update --app-id hare-app --switchback-test-id bunny-hop-routes \\
65
- --description "Optimizing hop paths through the meadow"[/green]
64
+ $ [dim]nextmv cloud switchback update --app-id hare-app --switchback-test-id bunny-hop-routes \\
65
+ --description "Optimizing hop paths through the meadow"[/dim]
66
66
 
67
67
  - Update both name and description and save the result.
68
- $ [green]nextmv cloud switchback update --app-id hare-app --switchback-test-id lettuce-delivery \\
68
+ $ [dim]nextmv cloud switchback update --app-id hare-app --switchback-test-id lettuce-delivery \\
69
69
  --name "Warren Lettuce Express" --description "Fast lettuce delivery to all burrows" \\
70
- --output updated-switchback-test.json[/green]
70
+ --output updated-switchback-test.json[/dim]
71
71
  """
72
72
 
73
73
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -23,10 +23,10 @@ def create(
23
23
  [bold][underline]Examples[/underline][/bold]
24
24
 
25
25
  - Create an upload URL for application [magenta]hare-app[/magenta].
26
- $ [green]nextmv cloud upload create --app-id hare-app[/green]
26
+ $ [dim]nextmv cloud upload create --app-id hare-app[/dim]
27
27
 
28
28
  - Create an upload URL for application [magenta]hare-app[/magenta] using profile [magenta]hare[/magenta].
29
- $ [green]nextmv cloud upload create --app-id hare-app --profile hare[/green]
29
+ $ [dim]nextmv cloud upload create --app-id hare-app --profile hare[/dim]
30
30
  """
31
31
 
32
32
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -58,28 +58,27 @@ def create(
58
58
  """
59
59
  Create a new Nextmv Cloud application version.
60
60
 
61
- Use the [code]--exist-ok[/code] flag to avoid errors when creating a
62
- version with an ID that already exists. This is useful for scripts that
63
- need to ensure a version exists without worrying about whether it was
64
- created previously.
61
+ Use the --exist-ok flag to avoid errors when creating a version with an ID
62
+ that already exists. This is useful for scripts that need to ensure a
63
+ version exists without worrying about whether it was created previously.
65
64
 
66
65
  [bold][underline]Examples[/underline][/bold]
67
66
 
68
67
  - Create a version for application [magenta]hare-app[/magenta]. A random ID will be generated.
69
- $ [green]nextmv cloud version create --app-id hare-app[/green]
68
+ $ [dim]nextmv cloud version create --app-id hare-app[/dim]
70
69
 
71
70
  - Create a version with a specific name.
72
- $ [green]nextmv cloud version create --app-id hare-app --name "v1.0.0"[/green]
71
+ $ [dim]nextmv cloud version create --app-id hare-app --name "v1.0.0"[/dim]
73
72
 
74
73
  - Create a version with a specific ID.
75
- $ [green]nextmv cloud version create --app-id hare-app --version-id v1[/green]
74
+ $ [dim]nextmv cloud version create --app-id hare-app --version-id v1[/dim]
76
75
 
77
76
  - Create a version with a name and description.
78
- $ [green]nextmv cloud version create --app-id hare-app --name "v1.0.0" \\
79
- --description "Initial release with routing optimization"[/green]
77
+ $ [dim]nextmv cloud version create --app-id hare-app --name "v1.0.0" \\
78
+ --description "Initial release with routing optimization"[/dim]
80
79
 
81
80
  - Create a version, or get it if it already exists.
82
- $ [green]nextmv cloud version create --app-id hare-app --version-id v1 --exist-ok[/green]
81
+ $ [dim]nextmv cloud version create --app-id hare-app --version-id v1 --exist-ok[/dim]
83
82
  """
84
83
 
85
84
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -5,9 +5,9 @@ This module defines the cloud version delete command for the Nextmv CLI.
5
5
  from typing import Annotated
6
6
 
7
7
  import typer
8
- from rich.prompt import Confirm
9
8
 
10
9
  from nextmv.cli.configuration.config import build_app
10
+ from nextmv.cli.confirm import get_confirmation
11
11
  from nextmv.cli.message import info, success
12
12
  from nextmv.cli.options import AppIDOption, ProfileOption, VersionIDOption
13
13
 
@@ -32,23 +32,22 @@ def delete(
32
32
  """
33
33
  Deletes a Nextmv Cloud application version.
34
34
 
35
- This action is permanent and cannot be undone. Use the [code]--yes[/code]
35
+ This action is permanent and cannot be undone. Use the --yes
36
36
  flag to skip the confirmation prompt.
37
37
 
38
38
  [bold][underline]Examples[/underline][/bold]
39
39
 
40
40
  - Delete the version with the ID [magenta]v1[/magenta] from application [magenta]hare-app[/magenta].
41
- $ [green]nextmv cloud version delete --app-id hare-app --version-id v1[/green]
41
+ $ [dim]nextmv cloud version delete --app-id hare-app --version-id v1[/dim]
42
42
 
43
43
  - Delete the version without confirmation prompt.
44
- $ [green]nextmv cloud version delete --app-id hare-app --version-id v1 --yes[/green]
44
+ $ [dim]nextmv cloud version delete --app-id hare-app --version-id v1 --yes[/dim]
45
45
  """
46
46
 
47
47
  if not yes:
48
- confirm = Confirm.ask(
48
+ confirm = get_confirmation(
49
49
  f"Are you sure you want to delete version [magenta]{version_id}[/magenta] "
50
50
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
51
- default=False,
52
51
  )
53
52
 
54
53
  if not confirm:
@@ -27,10 +27,10 @@ def exists(
27
27
  [bold][underline]Examples[/underline][/bold]
28
28
 
29
29
  - Check if the version with the ID [magenta]v1[/magenta] exists in application [magenta]hare-app[/magenta].
30
- $ [green]nextmv cloud version exists --app-id hare-app --version-id v1[/green]
30
+ $ [dim]nextmv cloud version exists --app-id hare-app --version-id v1[/dim]
31
31
 
32
32
  - Check if the version exists using the profile named [magenta]hare[/magenta].
33
- $ [green]nextmv cloud version exists --app-id hare-app --version-id v1 --profile hare[/green]
33
+ $ [dim]nextmv cloud version exists --app-id hare-app --version-id v1 --profile hare[/dim]
34
34
  """
35
35
 
36
36
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -39,11 +39,11 @@ def get(
39
39
  [bold][underline]Examples[/underline][/bold]
40
40
 
41
41
  - Get the version with the ID [magenta]v1[/magenta] from application [magenta]hare-app[/magenta].
42
- $ [green]nextmv cloud version get --app-id hare-app --version-id v1[/green]
42
+ $ [dim]nextmv cloud version get --app-id hare-app --version-id v1[/dim]
43
43
 
44
44
  - Get the version with the ID [magenta]v1[/magenta] and save the information to a
45
45
  [magenta]version.json[/magenta] file.
46
- $ [green]nextmv cloud version get --app-id hare-app --version-id v1 --output version.json[/green]
46
+ $ [dim]nextmv cloud version get --app-id hare-app --version-id v1 --output version.json[/dim]
47
47
  """
48
48
 
49
49
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -35,13 +35,13 @@ def list(
35
35
  [bold][underline]Examples[/underline][/bold]
36
36
 
37
37
  - List all versions of application [magenta]hare-app[/magenta].
38
- $ [green]nextmv cloud version list --app-id hare-app[/green]
38
+ $ [dim]nextmv cloud version list --app-id hare-app[/dim]
39
39
 
40
40
  - List all versions using the profile named [magenta]hare[/magenta].
41
- $ [green]nextmv cloud version list --app-id hare-app --profile hare[/green]
41
+ $ [dim]nextmv cloud version list --app-id hare-app --profile hare[/dim]
42
42
 
43
43
  - List all versions and save the information to a [magenta]versions.json[/magenta] file.
44
- $ [green]nextmv cloud version list --app-id hare-app --output versions.json[/green]
44
+ $ [dim]nextmv cloud version list --app-id hare-app --output versions.json[/dim]
45
45
  """
46
46
 
47
47
  cloud_app = build_app(app_id=app_id, profile=profile)
@@ -54,23 +54,23 @@ def update(
54
54
  [bold][underline]Examples[/underline][/bold]
55
55
 
56
56
  - Update a version's name.
57
- $ [green]nextmv cloud version update --app-id hare-app --version-id v1 --name "Version 1.0"[/green]
57
+ $ [dim]nextmv cloud version update --app-id hare-app --version-id v1 --name "Version 1.0"[/dim]
58
58
 
59
59
  - Update a version's description.
60
- $ [green]nextmv cloud version update --app-id hare-app --version-id v1 \\
61
- --description "Initial stable release"[/green]
60
+ $ [dim]nextmv cloud version update --app-id hare-app --version-id v1 \\
61
+ --description "Initial stable release"[/dim]
62
62
 
63
63
  - Update a version's name and description at once.
64
- $ [green]nextmv cloud version update --app-id hare-app --version-id v1 \\
65
- --name "Version 1.0" --description "Initial stable release"[/green]
64
+ $ [dim]nextmv cloud version update --app-id hare-app --version-id v1 \\
65
+ --name "Version 1.0" --description "Initial stable release"[/dim]
66
66
 
67
67
  - Update a version and save the updated information to a [magenta]updated_version.json[/magenta] file.
68
- $ [green]nextmv cloud version update --app-id hare-app --version-id v1 \\
69
- --name "Version 1.0" --output updated_version.json[/green]
68
+ $ [dim]nextmv cloud version update --app-id hare-app --version-id v1 \\
69
+ --name "Version 1.0" --output updated_version.json[/dim]
70
70
  """
71
71
 
72
72
  if name is None and description is None:
73
- error("Provide at least one option to update: [code]--name[/code] or [code]--description[/code].")
73
+ error("Provide at least one option to update: --name or --description.")
74
74
 
75
75
  cloud_app = build_app(app_id=app_id, profile=profile)
76
76
  updated_version = cloud_app.update_version(
@@ -53,35 +53,35 @@ def clone(
53
53
  Clone a community app locally.
54
54
 
55
55
  By default, the [magenta]latest[/magenta] version will be used. You can
56
- specify a version with the [code]--version[/code] flag, and customize the
57
- output directory with the [code]--directory[/code] flag. If you want to
58
- list the available apps, use the [code]nextmv community list[/code] command.
56
+ specify a version with the --version flag, and customize the output
57
+ directory with the --directory flag. If you want to list the available
58
+ apps, use the [code]nextmv community list[/code] command.
59
59
 
60
60
  [bold][underline]Examples[/underline][/bold]
61
61
 
62
62
  - Clone the [magenta]go-nextroute[/magenta] community app (under the
63
63
  [magenta]"go-nextroute"[/magenta] directory), using the [magenta]latest[/magenta] version.
64
- $ [green]nextmv community clone --app go-nextroute[/green]
64
+ $ [dim]nextmv community clone --app go-nextroute[/dim]
65
65
 
66
66
  - Clone the [magenta]go-nextroute[/magenta] community app under the
67
67
  [magenta]"~/sample/my_app"[/magenta] directory, using the [magenta]latest[/magenta] version.
68
- $ [green]nextmv community clone --app go-nextroute --directory ~/sample/my_app[/green]
68
+ $ [dim]nextmv community clone --app go-nextroute --directory ~/sample/my_app[/dim]
69
69
 
70
70
  - Clone the [magenta]go-nextroute[/magenta] community app (under the
71
71
  [magenta]"go-nextroute"[/magenta] directory), using version [magenta]v1.2.0[/magenta].
72
- $ [green]nextmv community clone --app go-nextroute --version v1.2.0[/green]
72
+ $ [dim]nextmv community clone --app go-nextroute --version v1.2.0[/dim]
73
73
 
74
74
  - Clone the [magenta]go-nextroute[/magenta] community app (under the
75
75
  [magenta]"go-nextroute"[/magenta] directory), using the [magenta]latest[/magenta] version
76
76
  and a profile named [magenta]hare[/magenta].
77
- $ [green]nextmv community clone --app go-nextroute --profile hare[/green]
77
+ $ [dim]nextmv community clone --app go-nextroute --profile hare[/dim]
78
78
  """
79
79
 
80
80
  manifest = download_manifest(profile=profile)
81
81
  app_obj = find_app(manifest, app)
82
82
 
83
83
  if version is not None and version == "":
84
- error("The [code]--version[/code] flag cannot be an empty string.")
84
+ error("The --version flag cannot be an empty string.")
85
85
 
86
86
  if not app_has_version(app_obj, version):
87
87
  # We don't use error() here to allow printing something before exiting.
@@ -97,8 +97,10 @@ def clone(
97
97
  if version == LATEST_VERSION:
98
98
  version = app_obj.get("latest_app_version")
99
99
 
100
- destination = directory
101
- if directory is None or directory == "":
100
+ # Clean and normalize directory path in an OS-independent way
101
+ if directory is not None and directory != "":
102
+ destination = os.path.normpath(directory)
103
+ else:
102
104
  destination = app
103
105
 
104
106
  full_destination = get_valid_path(destination, os.stat)
@@ -37,30 +37,30 @@ def list(
37
37
  """
38
38
  List the available community apps
39
39
 
40
- Use the [code]--app[/code] flag to list that app's versions. Use the
41
- [code]--flat[/code] flag to flatten the list of names/versions. If you
42
- want to clone a community app locally, use the [code]nextmv community clone[/code] command.
40
+ Use the --app flag to list that app's versions. Use the --flat flag to
41
+ flatten the list of names/versions. If you want to clone a community app
42
+ locally, use the [code]nextmv community clone[/code] command.
43
43
 
44
44
  [bold][underline]Examples[/underline][/bold]
45
45
 
46
46
  - List the available community apps.
47
- $ [green]nextmv community list[/green]
47
+ $ [dim]nextmv community list[/dim]
48
48
 
49
49
  - List the available versions of the [magenta]go-nextroute[/magenta] community app.
50
- $ [green]nextmv community list --app go-nextroute[/green]
50
+ $ [dim]nextmv community list --app go-nextroute[/dim]
51
51
 
52
52
  - List the names of the available community apps as a flat list.
53
- $ [green]nextmv community list --flat[/green]
53
+ $ [dim]nextmv community list --flat[/dim]
54
54
 
55
55
  - List the available versions of the [magenta]go-nextroute[/magenta] community app as a flat list.
56
- $ [green]nextmv community list --app go-nextroute --flat[/green]
56
+ $ [dim]nextmv community list --app go-nextroute --flat[/dim]
57
57
 
58
58
  - List the available community apps using a profile named [magenta]hare[/magenta].
59
- $ [green]nextmv community list --profile hare[/green]
59
+ $ [dim]nextmv community list --profile hare[/dim]
60
60
  """
61
61
 
62
62
  if app is not None and app == "":
63
- error("The [code]--app[/code] flag cannot be an empty string.")
63
+ error("The --app flag cannot be an empty string.")
64
64
 
65
65
  manifest = download_manifest(profile=profile)
66
66
  if flat and app is None: