nextmv 1.0.0__py3-none-any.whl → 1.0.0.dev0__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.
- nextmv/__about__.py +1 -1
- nextmv/__entrypoint__.py +2 -1
- nextmv/__init__.py +4 -0
- nextmv/cli/CONTRIBUTING.md +40 -112
- nextmv/cli/cloud/__init__.py +0 -4
- nextmv/cli/cloud/acceptance/create.py +22 -20
- nextmv/cli/cloud/acceptance/delete.py +12 -8
- nextmv/cli/cloud/acceptance/get.py +10 -9
- nextmv/cli/cloud/acceptance/list.py +3 -3
- nextmv/cli/cloud/acceptance/update.py +6 -6
- nextmv/cli/cloud/account/__init__.py +3 -3
- nextmv/cli/cloud/account/create.py +11 -11
- nextmv/cli/cloud/account/delete.py +8 -7
- nextmv/cli/cloud/account/get.py +3 -3
- nextmv/cli/cloud/account/update.py +5 -5
- nextmv/cli/cloud/app/create.py +26 -25
- nextmv/cli/cloud/app/delete.py +7 -6
- nextmv/cli/cloud/app/exists.py +2 -2
- nextmv/cli/cloud/app/get.py +2 -2
- nextmv/cli/cloud/app/list.py +3 -3
- nextmv/cli/cloud/app/push.py +54 -349
- nextmv/cli/cloud/app/update.py +12 -12
- nextmv/cli/cloud/batch/create.py +28 -26
- nextmv/cli/cloud/batch/delete.py +10 -6
- nextmv/cli/cloud/batch/get.py +9 -9
- nextmv/cli/cloud/batch/list.py +3 -3
- nextmv/cli/cloud/batch/metadata.py +4 -4
- nextmv/cli/cloud/batch/update.py +6 -6
- nextmv/cli/cloud/data/__init__.py +1 -1
- nextmv/cli/cloud/data/upload.py +15 -15
- nextmv/cli/cloud/ensemble/__init__.py +0 -2
- nextmv/cli/cloud/ensemble/create.py +22 -21
- nextmv/cli/cloud/ensemble/delete.py +10 -6
- nextmv/cli/cloud/ensemble/get.py +4 -4
- nextmv/cli/cloud/ensemble/update.py +9 -9
- nextmv/cli/cloud/input_set/__init__.py +0 -2
- nextmv/cli/cloud/input_set/create.py +22 -22
- nextmv/cli/cloud/input_set/get.py +3 -3
- nextmv/cli/cloud/input_set/list.py +3 -3
- nextmv/cli/cloud/input_set/update.py +24 -24
- nextmv/cli/cloud/instance/create.py +15 -14
- nextmv/cli/cloud/instance/delete.py +7 -6
- nextmv/cli/cloud/instance/exists.py +2 -2
- nextmv/cli/cloud/instance/get.py +2 -2
- nextmv/cli/cloud/instance/list.py +3 -3
- nextmv/cli/cloud/instance/update.py +14 -14
- nextmv/cli/cloud/managed_input/create.py +16 -14
- nextmv/cli/cloud/managed_input/delete.py +8 -7
- nextmv/cli/cloud/managed_input/get.py +3 -3
- nextmv/cli/cloud/managed_input/list.py +3 -3
- nextmv/cli/cloud/managed_input/update.py +9 -9
- nextmv/cli/cloud/run/cancel.py +2 -2
- nextmv/cli/cloud/run/create.py +40 -34
- nextmv/cli/cloud/run/get.py +8 -8
- nextmv/cli/cloud/run/input.py +4 -4
- nextmv/cli/cloud/run/list.py +6 -6
- nextmv/cli/cloud/run/logs.py +10 -9
- nextmv/cli/cloud/run/metadata.py +4 -4
- nextmv/cli/cloud/run/track.py +33 -32
- nextmv/cli/cloud/scenario/create.py +21 -21
- nextmv/cli/cloud/scenario/delete.py +10 -6
- nextmv/cli/cloud/scenario/get.py +9 -9
- nextmv/cli/cloud/scenario/list.py +3 -3
- nextmv/cli/cloud/scenario/metadata.py +4 -4
- nextmv/cli/cloud/scenario/update.py +6 -6
- nextmv/cli/cloud/secrets/create.py +17 -17
- nextmv/cli/cloud/secrets/delete.py +10 -6
- nextmv/cli/cloud/secrets/get.py +4 -4
- nextmv/cli/cloud/secrets/list.py +3 -3
- nextmv/cli/cloud/secrets/update.py +20 -17
- nextmv/cli/cloud/upload/create.py +2 -2
- nextmv/cli/cloud/version/create.py +10 -9
- nextmv/cli/cloud/version/delete.py +7 -6
- nextmv/cli/cloud/version/exists.py +2 -2
- nextmv/cli/cloud/version/get.py +2 -2
- nextmv/cli/cloud/version/list.py +3 -3
- nextmv/cli/cloud/version/update.py +8 -8
- nextmv/cli/community/__init__.py +1 -1
- nextmv/cli/community/clone.py +204 -20
- nextmv/cli/community/list.py +125 -60
- nextmv/cli/configuration/config.py +10 -43
- nextmv/cli/configuration/create.py +7 -7
- nextmv/cli/configuration/delete.py +8 -8
- nextmv/cli/configuration/list.py +3 -3
- nextmv/cli/main.py +36 -26
- nextmv/cli/message.py +54 -71
- nextmv/cli/options.py +0 -28
- nextmv/cli/version.py +1 -1
- nextmv/cloud/__init__.py +38 -14
- nextmv/cloud/acceptance_test.py +65 -1
- nextmv/cloud/account.py +6 -1
- nextmv/cloud/application/__init__.py +75 -18
- nextmv/cloud/application/_acceptance.py +8 -13
- nextmv/cloud/application/_batch_scenario.py +19 -4
- nextmv/cloud/application/_input_set.py +6 -42
- nextmv/cloud/application/_instance.py +3 -3
- nextmv/cloud/application/_managed_input.py +2 -2
- nextmv/cloud/application/_version.py +3 -4
- nextmv/cloud/batch_experiment.py +1 -3
- nextmv/cloud/integration.py +4 -7
- nextmv/deprecated.py +3 -5
- nextmv/input.py +52 -0
- nextmv/local/runner.py +1 -1
- nextmv/model.py +11 -50
- nextmv/options.py +256 -11
- nextmv/output.py +62 -0
- nextmv/run.py +10 -1
- nextmv/status.py +51 -1
- {nextmv-1.0.0.dist-info → nextmv-1.0.0.dev0.dist-info}/METADATA +4 -5
- nextmv-1.0.0.dev0.dist-info/RECORD +158 -0
- nextmv/cli/cloud/ensemble/list.py +0 -63
- nextmv/cli/cloud/input_set/delete.py +0 -64
- nextmv/cli/cloud/shadow/__init__.py +0 -33
- nextmv/cli/cloud/shadow/create.py +0 -184
- nextmv/cli/cloud/shadow/delete.py +0 -64
- nextmv/cli/cloud/shadow/get.py +0 -61
- nextmv/cli/cloud/shadow/list.py +0 -63
- nextmv/cli/cloud/shadow/metadata.py +0 -66
- nextmv/cli/cloud/shadow/start.py +0 -43
- nextmv/cli/cloud/shadow/stop.py +0 -53
- nextmv/cli/cloud/shadow/update.py +0 -96
- nextmv/cli/cloud/switchback/__init__.py +0 -33
- nextmv/cli/cloud/switchback/create.py +0 -151
- nextmv/cli/cloud/switchback/delete.py +0 -64
- nextmv/cli/cloud/switchback/get.py +0 -62
- nextmv/cli/cloud/switchback/list.py +0 -63
- nextmv/cli/cloud/switchback/metadata.py +0 -68
- nextmv/cli/cloud/switchback/start.py +0 -43
- nextmv/cli/cloud/switchback/stop.py +0 -53
- nextmv/cli/cloud/switchback/update.py +0 -96
- nextmv/cli/confirm.py +0 -34
- nextmv/cloud/application/_shadow.py +0 -320
- nextmv/cloud/application/_switchback.py +0 -332
- nextmv/cloud/community.py +0 -446
- nextmv/cloud/shadow.py +0 -254
- nextmv/cloud/switchback.py +0 -228
- nextmv-1.0.0.dist-info/RECORD +0 -185
- nextmv-1.0.0.dist-info/entry_points.txt +0 -2
- {nextmv-1.0.0.dist-info → nextmv-1.0.0.dev0.dist-info}/WHEEL +0 -0
- {nextmv-1.0.0.dist-info → nextmv-1.0.0.dev0.dist-info}/licenses/LICENSE +0 -0
nextmv/cli/cloud/app/push.py
CHANGED
|
@@ -2,18 +2,12 @@
|
|
|
2
2
|
This module defines the cloud app push command for the Nextmv CLI.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import sys
|
|
6
|
-
from datetime import datetime, timezone
|
|
7
5
|
from typing import Annotated
|
|
8
6
|
|
|
9
7
|
import typer
|
|
10
|
-
from rich.prompt import Prompt
|
|
11
8
|
|
|
12
9
|
from nextmv.cli.configuration.config import build_app
|
|
13
|
-
from nextmv.cli.confirm import get_confirmation
|
|
14
|
-
from nextmv.cli.message import error, in_progress, info, success
|
|
15
10
|
from nextmv.cli.options import AppIDOption, ProfileOption
|
|
16
|
-
from nextmv.cloud.application import Application
|
|
17
11
|
from nextmv.manifest import Manifest
|
|
18
12
|
|
|
19
13
|
# Set up subcommand application.
|
|
@@ -41,48 +35,44 @@ def push(
|
|
|
41
35
|
metavar="MANIFEST_PATH",
|
|
42
36
|
),
|
|
43
37
|
] = None,
|
|
44
|
-
|
|
38
|
+
no_version: Annotated[
|
|
39
|
+
bool,
|
|
40
|
+
typer.Option(
|
|
41
|
+
"--no-version",
|
|
42
|
+
"-n",
|
|
43
|
+
help="The application will be pushed without creating a new version. "
|
|
44
|
+
"Default is to create a new version on each push.",
|
|
45
|
+
rich_help_panel="Versioning control",
|
|
46
|
+
),
|
|
47
|
+
] = False,
|
|
45
48
|
version_id: Annotated[
|
|
46
49
|
str | None,
|
|
47
50
|
typer.Option(
|
|
48
51
|
"--version-id",
|
|
49
52
|
"-v",
|
|
50
|
-
help="Custom ID
|
|
51
|
-
"
|
|
53
|
+
help="Custom version ID when pushing the application. Automatically generated if not provided.",
|
|
54
|
+
rich_help_panel="Versioning control",
|
|
52
55
|
metavar="VERSION_ID",
|
|
53
|
-
rich_help_panel="Version control",
|
|
54
56
|
),
|
|
55
57
|
] = None,
|
|
56
|
-
|
|
57
|
-
bool,
|
|
58
|
-
typer.Option(
|
|
59
|
-
"--version-yes",
|
|
60
|
-
"-y",
|
|
61
|
-
help="Create a new version after push. Skips confirmation prompt. Useful for non-interactive sessions.",
|
|
62
|
-
rich_help_panel="Version control",
|
|
63
|
-
),
|
|
64
|
-
] = False,
|
|
65
|
-
# Options for instance control.
|
|
66
|
-
create_instance_id: Annotated[
|
|
58
|
+
version_name: Annotated[
|
|
67
59
|
str | None,
|
|
68
60
|
typer.Option(
|
|
69
|
-
"--
|
|
70
|
-
"-
|
|
71
|
-
help="
|
|
72
|
-
"
|
|
73
|
-
metavar="
|
|
74
|
-
rich_help_panel="Instance control",
|
|
61
|
+
"--version-name",
|
|
62
|
+
"-e",
|
|
63
|
+
help="Custom version name when pushing the application. Automatically generated if not provided.",
|
|
64
|
+
rich_help_panel="Versioning control",
|
|
65
|
+
metavar="VERSION_NAME",
|
|
75
66
|
),
|
|
76
67
|
] = None,
|
|
77
|
-
|
|
68
|
+
version_description: Annotated[
|
|
78
69
|
str | None,
|
|
79
70
|
typer.Option(
|
|
80
|
-
"--
|
|
81
|
-
"-
|
|
82
|
-
help="
|
|
83
|
-
"
|
|
84
|
-
metavar="
|
|
85
|
-
rich_help_panel="Instance control",
|
|
71
|
+
"--version-description",
|
|
72
|
+
"-r",
|
|
73
|
+
help="Custom version description when pushing the application. Automatically generated if not provided.",
|
|
74
|
+
rich_help_panel="Versioning control",
|
|
75
|
+
metavar="VERSION_DESCRIPTION",
|
|
86
76
|
),
|
|
87
77
|
] = None,
|
|
88
78
|
profile: ProfileOption = None,
|
|
@@ -90,343 +80,58 @@ def push(
|
|
|
90
80
|
"""
|
|
91
81
|
Push (deploy) a Nextmv application to Nextmv Cloud.
|
|
92
82
|
|
|
93
|
-
Use the --app-dir option to specify the path to your
|
|
94
|
-
directory. By default, the current working directory is
|
|
83
|
+
Use the [code]--app-dir[/code] option to specify the path to your
|
|
84
|
+
application's root directory. By default, the current working directory is
|
|
85
|
+
used.
|
|
95
86
|
|
|
96
|
-
You can also provide a custom manifest file using the --manifest
|
|
97
|
-
not provided, the CLI will look for a file named
|
|
98
|
-
|
|
87
|
+
You can also provide a custom manifest file using the [code]--manifest[/code]
|
|
88
|
+
option. If not provided, the CLI will look for a file named [magenta]app.yaml[/magenta]
|
|
89
|
+
in the application's root.
|
|
99
90
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
--version-id, --create-instance-id, and --update-instance-id.
|
|
91
|
+
The default behavior of this command is to create a new application version
|
|
92
|
+
[italic]after[/italic] the app has been pushed. You can use the
|
|
93
|
+
[code]--no-version[/code] option to skip this step. The
|
|
94
|
+
[code]--version-...[/code] options allow you to customize the attributes of
|
|
95
|
+
the version that is created. If any of these options are not provided,
|
|
96
|
+
automatically generated values will be used.
|
|
107
97
|
|
|
108
98
|
[bold][underline]Examples[/underline][/bold]
|
|
109
99
|
|
|
110
100
|
- Push an application, with ID [magenta]hare-app[/magenta], from the current directory.
|
|
111
|
-
$ [
|
|
101
|
+
$ [green]nextmv cloud app push --app-id hare-app[/green]
|
|
112
102
|
|
|
113
103
|
- Push an application, with ID [magenta]hare-app[/magenta], from the [magenta]./my-app[/magenta] directory.
|
|
114
|
-
$ [
|
|
104
|
+
$ [green]nextmv cloud app push --app-id hare-app --app-dir ./my-app[/green]
|
|
115
105
|
|
|
116
106
|
- Push an application, with ID [magenta]hare-app[/magenta], using a custom manifest file.
|
|
117
|
-
$ [
|
|
107
|
+
$ [green]nextmv cloud app push --app-id hare-app --manifest ./custom-manifest.yaml[/green]
|
|
118
108
|
|
|
119
|
-
- Push
|
|
120
|
-
|
|
109
|
+
- Push an application, with ID [magenta]hare-app[/magenta], from a specific
|
|
110
|
+
[magenta]./my-app[/magenta] directory with a custom manifest under [magenta]./custom-manifest.yaml[/magenta].
|
|
111
|
+
$ [green]nextmv cloud app push --app-id hare-app --app-dir ./my-app \\
|
|
112
|
+
--manifest ./custom-manifest.yaml[/green]
|
|
121
113
|
|
|
122
|
-
- Push
|
|
123
|
-
$ [
|
|
114
|
+
- Push an application without creating a new version.
|
|
115
|
+
$ [green]nextmv cloud app push --app-id hare-app --no-version[/green]
|
|
124
116
|
|
|
125
|
-
- Push
|
|
126
|
-
$ [
|
|
117
|
+
- Push an application with a custom version ID.
|
|
118
|
+
$ [green]nextmv cloud app push --app-id hare-app --version-id v1.0.0[/green]
|
|
127
119
|
|
|
128
|
-
- Push
|
|
129
|
-
$ [
|
|
120
|
+
- Push an application with custom version ID, name, and description.
|
|
121
|
+
$ [green]nextmv cloud app push --app-id hare-app --version-id v1.0.0 \\
|
|
122
|
+
--version-name "Release 1.0.0" \\
|
|
123
|
+
--version-description "First stable release"[/green]
|
|
130
124
|
"""
|
|
131
125
|
|
|
132
126
|
cloud_app = build_app(app_id=app_id, profile=profile)
|
|
133
|
-
|
|
134
|
-
# If a version already exists, we cannot create it.
|
|
135
|
-
if version_id is not None and version_id != "":
|
|
136
|
-
exists = cloud_app.version_exists(version_id=version_id)
|
|
137
|
-
if exists:
|
|
138
|
-
error(
|
|
139
|
-
f"Version [magenta]{version_id}[/magenta] already exists for application [magenta]{app_id}[/magenta]."
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
# We cannot create and update an instance at the same time.
|
|
143
|
-
update_defined = update_instance_id is not None and update_instance_id != ""
|
|
144
|
-
create_defined = create_instance_id is not None and create_instance_id != ""
|
|
145
|
-
if update_defined and create_defined:
|
|
146
|
-
error("Cannot use --update-instance-id and --create-instance-id at the same time.")
|
|
147
|
-
|
|
148
|
-
# We cannot update an instance that does not exist.
|
|
149
|
-
if update_defined and not cloud_app.instance_exists(instance_id=update_instance_id):
|
|
150
|
-
error(
|
|
151
|
-
f"Used option --update-instance-id but the instance [magenta]{update_instance_id}[/magenta] "
|
|
152
|
-
"does not exist. Use --create-instance-id instead."
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
# We cannot create an instance that already exists.
|
|
156
|
-
if create_defined and cloud_app.instance_exists(instance_id=create_instance_id):
|
|
157
|
-
error(
|
|
158
|
-
f"Used option --create-instance-id but the instance [magenta]{create_instance_id}[/magenta] "
|
|
159
|
-
"already exists. Use --update-instance-id instead."
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
# Do the normal push first.
|
|
163
127
|
loaded_manifest = Manifest.from_yaml(dirpath=manifest) if manifest is not None and manifest != "" else None
|
|
164
128
|
cloud_app.push(
|
|
165
129
|
manifest=loaded_manifest,
|
|
166
130
|
app_dir=app_dir,
|
|
167
131
|
verbose=True,
|
|
168
132
|
rich_print=True,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
now = datetime.now(timezone.utc)
|
|
172
|
-
version_id, should_continue = _handle_version_creation(
|
|
173
|
-
cloud_app=cloud_app,
|
|
174
|
-
app_id=app_id,
|
|
175
|
-
version_id=version_id,
|
|
176
|
-
version_yes=version_yes,
|
|
177
|
-
now=now,
|
|
178
|
-
)
|
|
179
|
-
if not should_continue:
|
|
180
|
-
return
|
|
181
|
-
|
|
182
|
-
# If the override for updating an instance was used, we update the instance
|
|
183
|
-
# and we are done.
|
|
184
|
-
if update_defined:
|
|
185
|
-
info("Used option --update-instance-id to link version to existing instance.")
|
|
186
|
-
_update_instance(
|
|
187
|
-
cloud_app=cloud_app,
|
|
188
|
-
app_id=app_id,
|
|
189
|
-
version_id=version_id,
|
|
190
|
-
instance_id=update_instance_id,
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
# If the override for creating a new instance was used, we create the
|
|
196
|
-
# instance and we are done.
|
|
197
|
-
if create_defined:
|
|
198
|
-
info("Used option --create-instance-id to link version to new instance.")
|
|
199
|
-
_create_instance(
|
|
200
|
-
cloud_app=cloud_app,
|
|
201
|
-
app_id=app_id,
|
|
202
|
-
version_id=version_id,
|
|
203
|
-
instance_id=create_instance_id,
|
|
204
|
-
now=now,
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
return
|
|
208
|
-
|
|
209
|
-
# If no overrides are used, we handle instance prompting.
|
|
210
|
-
_handle_instance_prompting(
|
|
211
|
-
cloud_app=cloud_app,
|
|
212
|
-
app_id=app_id,
|
|
133
|
+
no_version=no_version,
|
|
213
134
|
version_id=version_id,
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
def _handle_version_creation(
|
|
219
|
-
cloud_app: Application,
|
|
220
|
-
app_id: str,
|
|
221
|
-
version_id: str | None,
|
|
222
|
-
version_yes: bool,
|
|
223
|
-
now: datetime,
|
|
224
|
-
) -> tuple[str, bool]:
|
|
225
|
-
"""
|
|
226
|
-
Handle the logic for version creation after pushing an application.
|
|
227
|
-
|
|
228
|
-
If a version ID is provided and exists, it is used directly. If not, the user is prompted (unless auto-confirmed)
|
|
229
|
-
to create a new version. If confirmed, a new version is created with an automatic description.
|
|
230
|
-
|
|
231
|
-
Parameters
|
|
232
|
-
----------
|
|
233
|
-
cloud_app : Application
|
|
234
|
-
The cloud application object to interact with Nextmv Cloud.
|
|
235
|
-
app_id : str
|
|
236
|
-
The application ID.
|
|
237
|
-
version_id : str or None
|
|
238
|
-
The version ID to use or check for existence. If None or empty, a new version may be created.
|
|
239
|
-
version_yes : bool
|
|
240
|
-
Whether to skip the prompt and auto-create a new version.
|
|
241
|
-
now : datetime
|
|
242
|
-
The current datetime, used for version description.
|
|
243
|
-
|
|
244
|
-
Returns
|
|
245
|
-
-------
|
|
246
|
-
tuple[str, bool]
|
|
247
|
-
A tuple containing the version ID (empty string if not created) and a boolean indicating
|
|
248
|
-
whether to continue with subsequent steps (True if a version is selected or created, False otherwise).
|
|
249
|
-
"""
|
|
250
|
-
|
|
251
|
-
# If the user provides a version, and it exists, we use it directly and we
|
|
252
|
-
# are done.
|
|
253
|
-
if version_id is not None and version_id != "":
|
|
254
|
-
info(f"Version [magenta]{version_id}[/magenta] does not exist. A new version will be created.")
|
|
255
|
-
version_yes = True # Activate auto-confirm since user provided a version ID.
|
|
256
|
-
|
|
257
|
-
# If we are not auto-confirming version creation, ask the user.
|
|
258
|
-
if not version_yes:
|
|
259
|
-
should_create = get_confirmation(
|
|
260
|
-
msg=f"Do you want to create a new version for application [magenta]{app_id}[/magenta] now?",
|
|
261
|
-
default=True,
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
# If the user does not want to create a new version, we are done.
|
|
265
|
-
if not should_create:
|
|
266
|
-
info("Will not create a new version.")
|
|
267
|
-
return "", False
|
|
268
|
-
|
|
269
|
-
# Create a new version if either the user confirms by prompt or by using
|
|
270
|
-
# the flag.
|
|
271
|
-
in_progress("Creating a new version...")
|
|
272
|
-
version_description = f"Version created automatically from push at {now.strftime('%Y-%m-%dT%H:%M:%SZ')}"
|
|
273
|
-
version = cloud_app.new_version(
|
|
274
|
-
id=version_id,
|
|
275
|
-
description=version_description,
|
|
276
|
-
)
|
|
277
|
-
version_id = version.id
|
|
278
|
-
success(f"New version [magenta]{version_id}[/magenta] created for application [magenta]{app_id}[/magenta].")
|
|
279
|
-
|
|
280
|
-
return version_id, True
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def _handle_instance_prompting(
|
|
284
|
-
cloud_app: Application,
|
|
285
|
-
app_id: str,
|
|
286
|
-
version_id: str,
|
|
287
|
-
now: datetime,
|
|
288
|
-
) -> None:
|
|
289
|
-
"""
|
|
290
|
-
Handle interactive prompting for linking a version to an instance after a push.
|
|
291
|
-
|
|
292
|
-
In interactive terminals, prompts the user to link the new version to an existing or new instance.
|
|
293
|
-
If the terminal is non-interactive, skips prompting. Handles both updating existing instances and creating new ones.
|
|
294
|
-
|
|
295
|
-
Parameters
|
|
296
|
-
----------
|
|
297
|
-
cloud_app : Application
|
|
298
|
-
The cloud application object to interact with Nextmv Cloud.
|
|
299
|
-
app_id : str
|
|
300
|
-
The application ID.
|
|
301
|
-
version_id : str
|
|
302
|
-
The version ID to link to an instance.
|
|
303
|
-
now : datetime
|
|
304
|
-
The current datetime, used for instance description if a new instance is created.
|
|
305
|
-
"""
|
|
306
|
-
|
|
307
|
-
# If this is not an interactive terminal, do not ask for instance linking,
|
|
308
|
-
# to avoid hanging indefinitely waiting for a user response.
|
|
309
|
-
if not sys.stdin.isatty():
|
|
310
|
-
info("Non-interactive terminal detected. Skipping instance linking.")
|
|
311
|
-
|
|
312
|
-
return
|
|
313
|
-
|
|
314
|
-
# Prompt the user for an instance ID to link the new version to.
|
|
315
|
-
instance_id = Prompt.ask(
|
|
316
|
-
f"Do you want to link version [magenta]{version_id}[/magenta] to an instance? If so, enter the instance ID. "
|
|
317
|
-
"Leave blank to abort",
|
|
318
|
-
case_sensitive=False,
|
|
319
|
-
)
|
|
320
|
-
if instance_id == "":
|
|
321
|
-
info("No instance ID provided. Skipping instance linking.")
|
|
322
|
-
return
|
|
323
|
-
|
|
324
|
-
# Based on whether the instance exists or not, ask the user if they want to
|
|
325
|
-
# update or create it.
|
|
326
|
-
exists = cloud_app.instance_exists(instance_id=instance_id)
|
|
327
|
-
|
|
328
|
-
# If the instance exists, ask if we want to update it.
|
|
329
|
-
if exists:
|
|
330
|
-
should_update = get_confirmation(
|
|
331
|
-
msg=f"Instance [magenta]{instance_id}[/magenta] exists. "
|
|
332
|
-
f"Do you want to link it to version [magenta]{version_id}[/magenta]?",
|
|
333
|
-
default=True,
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
if not should_update:
|
|
337
|
-
info(f"Will not update instance [magenta]{instance_id}[/magenta].")
|
|
338
|
-
return
|
|
339
|
-
|
|
340
|
-
_update_instance(
|
|
341
|
-
cloud_app=cloud_app,
|
|
342
|
-
app_id=app_id,
|
|
343
|
-
version_id=version_id,
|
|
344
|
-
instance_id=instance_id,
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
return
|
|
348
|
-
|
|
349
|
-
# If the instance does not exist, ask if we want to create it.
|
|
350
|
-
should_create = get_confirmation(
|
|
351
|
-
msg=f"Instance [magenta]{instance_id}[/magenta] does not exist. "
|
|
352
|
-
f"Do you want to create it using version [magenta]{version_id}[/magenta]?",
|
|
353
|
-
default=True,
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
if not should_create:
|
|
357
|
-
info(f"Will not create instance [magenta]{instance_id}[/magenta].")
|
|
358
|
-
return
|
|
359
|
-
|
|
360
|
-
_create_instance(
|
|
361
|
-
cloud_app=cloud_app,
|
|
362
|
-
app_id=app_id,
|
|
363
|
-
version_id=version_id,
|
|
364
|
-
instance_id=instance_id,
|
|
365
|
-
now=now,
|
|
366
|
-
)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
def _update_instance(
|
|
370
|
-
cloud_app: Application,
|
|
371
|
-
app_id: str,
|
|
372
|
-
version_id: str,
|
|
373
|
-
instance_id: str,
|
|
374
|
-
) -> None:
|
|
375
|
-
"""
|
|
376
|
-
Update an existing instance to use a new version.
|
|
377
|
-
|
|
378
|
-
Parameters
|
|
379
|
-
----------
|
|
380
|
-
cloud_app : Application
|
|
381
|
-
The cloud application object to interact with Nextmv Cloud.
|
|
382
|
-
app_id : str
|
|
383
|
-
The application ID.
|
|
384
|
-
version_id : str
|
|
385
|
-
The version ID to link to the instance.
|
|
386
|
-
instance_id : str
|
|
387
|
-
The instance ID to update.
|
|
388
|
-
"""
|
|
389
|
-
|
|
390
|
-
in_progress(f"Updating instance [magenta]{instance_id}[/magenta] to use version [magenta]{version_id}[/magenta]...")
|
|
391
|
-
cloud_app.update_instance(id=instance_id, version_id=version_id)
|
|
392
|
-
success(
|
|
393
|
-
f"Instance [magenta]{instance_id}[/magenta] updated to use version [magenta]{version_id}[/magenta] "
|
|
394
|
-
f"for application [magenta]{app_id}[/magenta]."
|
|
395
|
-
)
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
def _create_instance(
|
|
399
|
-
cloud_app: Application,
|
|
400
|
-
app_id: str,
|
|
401
|
-
version_id: str,
|
|
402
|
-
instance_id: str,
|
|
403
|
-
now: datetime,
|
|
404
|
-
) -> None:
|
|
405
|
-
"""
|
|
406
|
-
Create a new instance linked to a specific version.
|
|
407
|
-
|
|
408
|
-
Parameters
|
|
409
|
-
----------
|
|
410
|
-
cloud_app : Application
|
|
411
|
-
The cloud application object to interact with Nextmv Cloud.
|
|
412
|
-
app_id : str
|
|
413
|
-
The application ID.
|
|
414
|
-
version_id : str
|
|
415
|
-
The version ID to link to the new instance.
|
|
416
|
-
instance_id : str
|
|
417
|
-
The instance ID to create.
|
|
418
|
-
now : datetime
|
|
419
|
-
The current datetime, used for the instance description.
|
|
420
|
-
"""
|
|
421
|
-
|
|
422
|
-
in_progress(f"Creating a new instance with ID [magenta]{instance_id}[/magenta]...")
|
|
423
|
-
instance_description = f"Instance created automatically from push at {now.strftime('%Y-%m-%dT%H:%M:%SZ')}"
|
|
424
|
-
instance = cloud_app.new_instance(
|
|
425
|
-
version_id=version_id,
|
|
426
|
-
id=instance_id,
|
|
427
|
-
description=instance_description,
|
|
428
|
-
)
|
|
429
|
-
success(
|
|
430
|
-
f"New instance [magenta]{instance.id}[/magenta] created using version [magenta]{version_id}[/magenta] "
|
|
431
|
-
f"for application [magenta]{app_id}[/magenta]."
|
|
135
|
+
version_name=version_name,
|
|
136
|
+
version_description=version_description,
|
|
432
137
|
)
|
nextmv/cli/cloud/app/update.py
CHANGED
|
@@ -74,33 +74,33 @@ def update(
|
|
|
74
74
|
[bold][underline]Examples[/underline][/bold]
|
|
75
75
|
|
|
76
76
|
- Update an application's name.
|
|
77
|
-
$ [
|
|
77
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "New Hare App"[/green]
|
|
78
78
|
|
|
79
79
|
- Update an application's description.
|
|
80
|
-
$ [
|
|
81
|
-
--description "An updated description for routing hares"[/
|
|
80
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "Hare App" \\
|
|
81
|
+
--description "An updated description for routing hares"[/green]
|
|
82
82
|
|
|
83
83
|
- Update an application's default instance ID.
|
|
84
|
-
$ [
|
|
85
|
-
--default-instance-id burrow[/
|
|
84
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "Hare App" \\
|
|
85
|
+
--default-instance-id burrow[/green]
|
|
86
86
|
|
|
87
87
|
- Update an application's default experiment instance.
|
|
88
|
-
$ [
|
|
89
|
-
--default-experiment-instance experiment-v1[/
|
|
88
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "Hare App" \\
|
|
89
|
+
--default-experiment-instance experiment-v1[/green]
|
|
90
90
|
|
|
91
91
|
- Update multiple application properties at once.
|
|
92
|
-
$ [
|
|
92
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "Hare App" \\
|
|
93
93
|
--description "Updated description" --default-instance-id burrow \\
|
|
94
|
-
--default-experiment-instance experiment-v1[/
|
|
94
|
+
--default-experiment-instance experiment-v1[/green]
|
|
95
95
|
|
|
96
96
|
- Update an application and save the updated information to an [magenta]updated_app.json[/magenta] file.
|
|
97
|
-
$ [
|
|
97
|
+
$ [green]nextmv cloud app update --app-id hare-app --name "New Hare App" --output updated_app.json[/green]
|
|
98
98
|
"""
|
|
99
99
|
|
|
100
100
|
if name is None and description is None and default_instance_id is None and default_experiment_instance is None:
|
|
101
101
|
error(
|
|
102
|
-
"Provide at least one option to update: --name, --description, "
|
|
103
|
-
"--default-instance-id, or --default-experiment-instance."
|
|
102
|
+
"Provide at least one option to update: [code]--name[/code], [code]--description[/code], "
|
|
103
|
+
"[code]--default-instance-id[/code], or [code]--default-experiment-instance[/code]."
|
|
104
104
|
)
|
|
105
105
|
|
|
106
106
|
cloud_app = build_app(app_id=app_id, profile=profile)
|
nextmv/cli/cloud/batch/create.py
CHANGED
|
@@ -109,7 +109,7 @@ def create(
|
|
|
109
109
|
"--wait",
|
|
110
110
|
"-w",
|
|
111
111
|
help="Wait for the batch experiment to complete. Results are printed to [magenta]stdout[/magenta]. "
|
|
112
|
-
"Specify output location with --output.",
|
|
112
|
+
"Specify output location with [code]--output[/code].",
|
|
113
113
|
rich_help_panel="Output control",
|
|
114
114
|
),
|
|
115
115
|
] = False,
|
|
@@ -122,19 +122,21 @@ def create(
|
|
|
122
122
|
configurations. Each run is defined by a combination of input, instance or
|
|
123
123
|
version, and optional configuration options.
|
|
124
124
|
|
|
125
|
-
Use the --wait flag to wait for the batch experiment to
|
|
126
|
-
for results. Using the --output flag will
|
|
127
|
-
you to specify a destination file for the
|
|
125
|
+
Use the [code]--wait[/code] flag to wait for the batch experiment to
|
|
126
|
+
complete, polling for results. Using the [code]--output[/code] flag will
|
|
127
|
+
also activate waiting, and allows you to specify a destination file for the
|
|
128
|
+
results.
|
|
128
129
|
|
|
129
130
|
[bold][underline]Runs[/underline][/bold]
|
|
130
131
|
|
|
131
|
-
Runs are provided as [magenta]json[/magenta] objects using the
|
|
132
|
-
Each run defines what input, instance/version,
|
|
132
|
+
Runs are provided as [magenta]json[/magenta] objects using the
|
|
133
|
+
[code]--runs[/code] flag. Each run defines what input, instance/version,
|
|
134
|
+
and configuration to use.
|
|
133
135
|
|
|
134
136
|
You can provide runs in three ways:
|
|
135
137
|
- A single run as a [magenta]json[/magenta] object.
|
|
136
|
-
- Multiple runs by repeating the --runs flag.
|
|
137
|
-
- Multiple runs as a [magenta]json[/magenta] array in a single --runs flag.
|
|
138
|
+
- Multiple runs by repeating the [code]--runs[/code] flag.
|
|
139
|
+
- Multiple runs as a [magenta]json[/magenta] array in a single [code]--runs[/code] flag.
|
|
138
140
|
|
|
139
141
|
Each run must have the following fields:
|
|
140
142
|
- [magenta]input_id[/magenta]: ID of the input to use for this run
|
|
@@ -144,46 +146,46 @@ def create(
|
|
|
144
146
|
- [magenta]instance_id[/magenta] OR [magenta]version_id[/magenta]: Either an instance ID or
|
|
145
147
|
version ID must be provided (at least one required).
|
|
146
148
|
- [magenta]option_set[/magenta]: ID of the option set to use (optional).
|
|
147
|
-
Make sure to define the option sets using the --option-sets flag.
|
|
149
|
+
Make sure to define the option sets using the [code]--option-sets[/code] flag.
|
|
148
150
|
- [magenta]input_set_id[/magenta]: ID of the input set (optional).
|
|
149
151
|
- [magenta]scenario_id[/magenta]: Scenario ID if part of a scenario test (optional).
|
|
150
152
|
- [magenta]repetition[/magenta]: Repetition number (optional).
|
|
151
153
|
|
|
152
154
|
Object format:
|
|
153
|
-
[
|
|
155
|
+
[green]{
|
|
154
156
|
"input_id": "meadow-input-a1",
|
|
155
157
|
"instance_id": "bunny-hopper-v2",
|
|
156
158
|
"option_set": "speed-optimized",
|
|
157
159
|
"input_set_id": "spring-gardens"
|
|
158
|
-
}[/
|
|
160
|
+
}[/green]
|
|
159
161
|
|
|
160
162
|
[bold][underline]Option Sets[/underline][/bold]
|
|
161
163
|
|
|
162
164
|
Option sets are provided as a [magenta]json[/magenta] object using the
|
|
163
|
-
--option-sets flag. Option sets define named collections of
|
|
165
|
+
[code]--option-sets[/code] flag. Option sets define named collections of
|
|
164
166
|
runtime options that can be referenced by runs.
|
|
165
167
|
|
|
166
168
|
The option sets object is a dictionary where keys are option set IDs and
|
|
167
169
|
values are dictionaries of string key-value pairs representing the options.
|
|
168
170
|
|
|
169
171
|
Object format:
|
|
170
|
-
[
|
|
172
|
+
[green]{
|
|
171
173
|
"speed-optimized": {"timeout": "30", "algorithm": "fast"},
|
|
172
174
|
"quality-focused": {"timeout": "300", "algorithm": "thorough"}
|
|
173
|
-
}[/
|
|
175
|
+
}[/green]
|
|
174
176
|
|
|
175
177
|
[bold][underline]Examples[/underline][/bold]
|
|
176
178
|
|
|
177
179
|
- Create a batch experiment with a single run.
|
|
178
|
-
$ [
|
|
180
|
+
$ [green]RUN='{
|
|
179
181
|
"input_id": "carrot-patch-a",
|
|
180
182
|
"instance_id": "warren-planner-v1"
|
|
181
183
|
}'
|
|
182
184
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id bunny-hop-test \\
|
|
183
|
-
--name "Spring Meadow Routes" --input-set-id spring-gardens --runs "$RUN"[/
|
|
185
|
+
--name "Spring Meadow Routes" --input-set-id spring-gardens --runs "$RUN"[/green]
|
|
184
186
|
|
|
185
187
|
- Create with multiple runs by repeating the flag.
|
|
186
|
-
$ [
|
|
188
|
+
$ [green]RUN1='{
|
|
187
189
|
"input_id": "lettuce-field-1",
|
|
188
190
|
"instance_id": "hop-optimizer"
|
|
189
191
|
}'
|
|
@@ -193,10 +195,10 @@ def create(
|
|
|
193
195
|
}'
|
|
194
196
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id lettuce-routes \\
|
|
195
197
|
--name "Lettuce Delivery Optimization" --input-set-id veggie-gardens \\
|
|
196
|
-
--runs "$RUN1" --runs "$RUN2"[/
|
|
198
|
+
--runs "$RUN1" --runs "$RUN2"[/green]
|
|
197
199
|
|
|
198
200
|
- Create with multiple runs in a single [magenta]json[/magenta] array.
|
|
199
|
-
$ [
|
|
201
|
+
$ [green]RUNS='[
|
|
200
202
|
{
|
|
201
203
|
"input_id": "warren-zone-a",
|
|
202
204
|
"instance_id": "burrow-builder"
|
|
@@ -207,28 +209,28 @@ def create(
|
|
|
207
209
|
}
|
|
208
210
|
]'
|
|
209
211
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id warren-expansion \\
|
|
210
|
-
--name "Warren Construction Plans" --input-set-id burrow-sites --runs "$RUNS"[/
|
|
212
|
+
--name "Warren Construction Plans" --input-set-id burrow-sites --runs "$RUNS"[/green]
|
|
211
213
|
|
|
212
214
|
- Create a batch experiment and wait for it to complete.
|
|
213
|
-
$ [
|
|
215
|
+
$ [green]RUN='{
|
|
214
216
|
"input_id": "carrot-harvest",
|
|
215
217
|
"instance_id": "foraging-route"
|
|
216
218
|
}'
|
|
217
219
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id harvest-time \\
|
|
218
220
|
--name "Autumn Carrot Collection" --input-set-id harvest-season \\
|
|
219
|
-
--runs "$RUN" --wait[/
|
|
221
|
+
--runs "$RUN" --wait[/green]
|
|
220
222
|
|
|
221
223
|
- Create a batch experiment and save the results to a file, waiting for completion.
|
|
222
|
-
$ [
|
|
224
|
+
$ [green]RUN='{
|
|
223
225
|
"input_id": "predator-zones",
|
|
224
226
|
"instance_id": "safe-hopper"
|
|
225
227
|
}'
|
|
226
228
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id safety-analysis \\
|
|
227
229
|
--name "Fox Avoidance Routes" --input-set-id danger-zones \\
|
|
228
|
-
--runs "$RUN" --output bunny-safety-results.json[/
|
|
230
|
+
--runs "$RUN" --output bunny-safety-results.json[/green]
|
|
229
231
|
|
|
230
232
|
- Create a batch experiment with option sets.
|
|
231
|
-
$ [
|
|
233
|
+
$ [green]RUN1='{
|
|
232
234
|
"input_id": "garden-route-1",
|
|
233
235
|
"instance_id": "hop-optimizer",
|
|
234
236
|
"option_set": "fast-hops"
|
|
@@ -244,7 +246,7 @@ def create(
|
|
|
244
246
|
}'
|
|
245
247
|
nextmv cloud batch create --app-id hare-app --batch-experiment-id hop-comparison \\
|
|
246
248
|
--name "Speed vs Safety Analysis" --input-set-id garden-paths \\
|
|
247
|
-
--runs "$RUN1" --runs "$RUN2" --option-sets "$OPTION_SETS"[/
|
|
249
|
+
--runs "$RUN1" --runs "$RUN2" --option-sets "$OPTION_SETS"[/green]
|
|
248
250
|
"""
|
|
249
251
|
|
|
250
252
|
cloud_app = build_app(app_id=app_id, profile=profile)
|