nextmv 1.0.0.dev10__py3-none-any.whl → 1.1.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 CHANGED
@@ -1 +1 @@
1
- __version__ = "v1.0.0.dev10"
1
+ __version__ = "v1.1.0.dev0"
@@ -17,6 +17,7 @@ from nextmv.cli.cloud.run import app as run_app
17
17
  from nextmv.cli.cloud.scenario import app as scenario_app
18
18
  from nextmv.cli.cloud.secrets import app as secrets_app
19
19
  from nextmv.cli.cloud.shadow import app as shadow_app
20
+ from nextmv.cli.cloud.sso import app as sso_app
20
21
  from nextmv.cli.cloud.switchback import app as switchback_app
21
22
  from nextmv.cli.cloud.upload import app as upload_app
22
23
  from nextmv.cli.cloud.version import app as version_app
@@ -36,6 +37,7 @@ app.add_typer(run_app, name="run")
36
37
  app.add_typer(scenario_app, name="scenario")
37
38
  app.add_typer(secrets_app, name="secrets")
38
39
  app.add_typer(shadow_app, name="shadow")
40
+ app.add_typer(sso_app, name="sso")
39
41
  app.add_typer(switchback_app, name="switchback")
40
42
  app.add_typer(upload_app, name="upload")
41
43
  app.add_typer(version_app, name="version")
@@ -20,9 +20,11 @@ app.add_typer(update_app)
20
20
  @app.callback()
21
21
  def callback() -> None:
22
22
  """
23
- Manage SSO for your Nextmv Cloud account (organization).
23
+ Manage your Nextmv Cloud account (organization).
24
24
 
25
- Please contact [link=https://www.nextmv.io/contact][bold]Nextmv support[/bold][/link]
26
- for assistance configuring SSO for your organization.
25
+ Please contact [link=https://www.nextmv.io/contact][bold]Nextmv
26
+ support[/bold][/link] for assistance configuring SSO for your organization.
27
+ You may use the [code]nextmv cloud sso[/code] command tree to manage the
28
+ SSO configuration for your organization.
27
29
  """
28
30
  pass
@@ -42,7 +42,10 @@ def create(
42
42
  Create a new Nextmv Cloud account in your organization.
43
43
 
44
44
  To create managed accounts, SSO must be configured for your organization.
45
- Please contact [link=https://www.nextmv.io/contact][bold]Nextmv support[/bold][/link] for assistance.
45
+ Please contact [link=https://www.nextmv.io/contact][bold]Nextmv
46
+ support[/bold][/link] for assistance. You may use the [code]nextmv cloud
47
+ sso[/code] command tree to manage the SSO configuration for your
48
+ organization.
46
49
 
47
50
  At least one administrator email address must be provided. Multiple
48
51
  administrators can be specified by repeating the --admins flag or by
@@ -0,0 +1,32 @@
1
+ """
2
+ This module defines the cloud sso command tree for the Nextmv CLI.
3
+ """
4
+
5
+ import typer
6
+
7
+ from nextmv.cli.cloud.sso.create import app as create_app
8
+ from nextmv.cli.cloud.sso.delete import app as delete_app
9
+ from nextmv.cli.cloud.sso.disable import app as disable_app
10
+ from nextmv.cli.cloud.sso.enable import app as enable_app
11
+ from nextmv.cli.cloud.sso.get import app as get_app
12
+ from nextmv.cli.cloud.sso.update import app as update_app
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+ app.add_typer(create_app)
17
+ app.add_typer(delete_app)
18
+ app.add_typer(disable_app)
19
+ app.add_typer(enable_app)
20
+ app.add_typer(get_app)
21
+ app.add_typer(update_app)
22
+
23
+
24
+ @app.callback()
25
+ def callback() -> None:
26
+ """
27
+ Manage SSO for your Nextmv Cloud organization (account).
28
+
29
+ Please contact [link=https://www.nextmv.io/contact][bold]Nextmv support[/bold][/link]
30
+ for assistance configuring SSO for your organization.
31
+ """
32
+ pass
@@ -0,0 +1,97 @@
1
+ """
2
+ This module defines the cloud sso create command for the Nextmv CLI.
3
+ """
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from nextmv.cli.configuration.config import build_client
10
+ from nextmv.cli.message import in_progress, print_json
11
+ from nextmv.cli.options import ProfileOption
12
+ from nextmv.cloud.sso import SSOConfiguration
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+
17
+
18
+ @app.command()
19
+ def create(
20
+ allow_non_domain_users: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--allow-non-domain-users",
24
+ "-a",
25
+ help="Allow users who are not part of the SSO domain to access the Nextmv Cloud organization (account).",
26
+ ),
27
+ ] = False,
28
+ enabled: Annotated[
29
+ bool,
30
+ typer.Option(
31
+ "--enabled",
32
+ "-e",
33
+ help="Enable SSO for the Nextmv Cloud organization (account) at the time of creation. "
34
+ "Run [code]nextmv cloud sso enable[/code] to enable SSO after creation.",
35
+ ),
36
+ ] = False,
37
+ metadata_url: Annotated[
38
+ str | None,
39
+ typer.Option(
40
+ "--metadata-url",
41
+ "-u",
42
+ help="The URL to the SSO metadata document.",
43
+ metavar="METADATA_URL",
44
+ ),
45
+ ] = None,
46
+ metadata_document: Annotated[
47
+ str | None,
48
+ typer.Option(
49
+ "--metadata-document",
50
+ "-d",
51
+ help="The SSO metadata document as a string.",
52
+ metavar="METADATA_DOCUMENT",
53
+ ),
54
+ ] = None,
55
+ profile: ProfileOption = None,
56
+ ) -> None:
57
+ """
58
+ Create a new SSO configuration for your Nextmv Cloud organization.
59
+
60
+ SSO must be configured to enable managed accounts in your organization.
61
+ Please contact [link=https://www.nextmv.io/contact][bold]Nextmv support[/bold][/link] for assistance.
62
+
63
+ You must provide either a metadata URL or a metadata document. The metadata
64
+ document contains the SAML configuration details from your identity provider.
65
+
66
+ [bold][underline]Examples[/underline][/bold]
67
+
68
+ - Create an SSO configuration using a metadata URL.
69
+ $ [dim]nextmv cloud sso create --metadata-url "https://sso.carrotexpress.com/saml/metadata"[/dim]
70
+
71
+ - Create and enable SSO configuration immediately.
72
+ $ [dim]nextmv cloud sso create --metadata-url "https://sso.bunnylogistics.io/metadata" \\
73
+ --enabled[/dim]
74
+
75
+ - Create SSO configuration allowing non-domain users.
76
+ $ [dim]nextmv cloud sso create --metadata-url "https://idp.hopmail.com/saml/metadata" \\
77
+ --allow-non-domain-users[/dim]
78
+
79
+ - Create SSO configuration using a metadata document string.
80
+ $ [dim]nextmv cloud sso create --metadata-document "<EntityDescriptor ...</EntityDescriptor>"[/dim]
81
+
82
+ - Create SSO configuration using the profile named [magenta]hare[/magenta].
83
+ $ [dim]nextmv cloud sso create --metadata-url "https://sso.cottontailcouriers.net/metadata" \\
84
+ --profile hare[/dim]
85
+ """
86
+
87
+ cloud_client = build_client(profile)
88
+ in_progress(msg="Creating configuration...")
89
+
90
+ configuration = SSOConfiguration.new(
91
+ client=cloud_client,
92
+ allow_non_domain_users=allow_non_domain_users,
93
+ enabled=enabled,
94
+ metadata_url=metadata_url,
95
+ metadata_document=metadata_document,
96
+ )
97
+ print_json(configuration.to_dict())
@@ -0,0 +1,58 @@
1
+ """
2
+ This module defines the cloud sso delete command for the Nextmv CLI.
3
+ """
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from nextmv.cli.configuration.config import build_sso_config
10
+ from nextmv.cli.confirm import get_confirmation
11
+ from nextmv.cli.message import info, success
12
+ from nextmv.cli.options import ProfileOption
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+
17
+
18
+ @app.command()
19
+ def delete(
20
+ yes: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--yes",
24
+ "-y",
25
+ help="Agree to deletion confirmation prompt. Useful for non-interactive sessions.",
26
+ ),
27
+ ] = False,
28
+ profile: ProfileOption = None,
29
+ ) -> None:
30
+ """
31
+ Deletes the SSO configuration.
32
+
33
+ You must have the [magenta]administrator[/magenta] role on the organization in order to delete it.
34
+
35
+ This action is permanent and cannot be undone. Use the --yes
36
+ flag to skip the confirmation prompt.
37
+
38
+ [bold][underline]Examples[/underline][/bold]
39
+
40
+ - Delete the SSO configuration.
41
+ $ [dim]nextmv cloud sso delete[/dim]
42
+
43
+ - Delete the SSO configuration without confirmation prompt.
44
+ $ [dim]nextmv cloud sso delete --yes[/dim]
45
+ """
46
+
47
+ if not yes:
48
+ confirm = get_confirmation(
49
+ "Are you sure you want to delete the sso configuration? This action cannot be undone.",
50
+ )
51
+
52
+ if not confirm:
53
+ info("SSO configuration will not be deleted.")
54
+ return
55
+
56
+ sso_config = build_sso_config(profile)
57
+ sso_config.delete()
58
+ success("SSO configuration has been deleted.")
@@ -0,0 +1,56 @@
1
+ """
2
+ This module defines the cloud sso disable command for the Nextmv CLI.
3
+ """
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from nextmv.cli.configuration.config import build_sso_config
10
+ from nextmv.cli.confirm import get_confirmation
11
+ from nextmv.cli.message import info, success
12
+ from nextmv.cli.options import ProfileOption
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+
17
+
18
+ @app.command()
19
+ def disable(
20
+ yes: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--yes",
24
+ "-y",
25
+ help="Agree to disable confirmation prompt. Useful for non-interactive sessions.",
26
+ ),
27
+ ] = False,
28
+ profile: ProfileOption = None,
29
+ ) -> None:
30
+ """
31
+ Disables the SSO configuration.
32
+
33
+ Use the --yes flag to skip the confirmation prompt. Use the [code]nextmv
34
+ cloud sso enable[/code] command to re-enable SSO.
35
+
36
+ [bold][underline]Examples[/underline][/bold]
37
+
38
+ - Disable the SSO configuration.
39
+ $ [dim]nextmv cloud sso disable[/dim]
40
+
41
+ - Disable the SSO configuration without confirmation prompt.
42
+ $ [dim]nextmv cloud sso disable --yes[/dim]
43
+ """
44
+
45
+ if not yes:
46
+ confirm = get_confirmation(
47
+ "Are you sure you want to disable the sso configuration?.",
48
+ )
49
+
50
+ if not confirm:
51
+ info("SSO configuration will not be disabled.")
52
+ return
53
+
54
+ sso_config = build_sso_config(profile)
55
+ sso_config.disable()
56
+ success("SSO configuration has been disabled.")
@@ -0,0 +1,56 @@
1
+ """
2
+ This module defines the cloud sso enable command for the Nextmv CLI.
3
+ """
4
+
5
+ from typing import Annotated
6
+
7
+ import typer
8
+
9
+ from nextmv.cli.configuration.config import build_sso_config
10
+ from nextmv.cli.confirm import get_confirmation
11
+ from nextmv.cli.message import info, success
12
+ from nextmv.cli.options import ProfileOption
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+
17
+
18
+ @app.command()
19
+ def enable(
20
+ yes: Annotated[
21
+ bool,
22
+ typer.Option(
23
+ "--yes",
24
+ "-y",
25
+ help="Agree to enable confirmation prompt. Useful for non-interactive sessions.",
26
+ ),
27
+ ] = False,
28
+ profile: ProfileOption = None,
29
+ ) -> None:
30
+ """
31
+ Enables the SSO configuration.
32
+
33
+ Use the --yes flag to skip the confirmation prompt. Use the [code]nextmv
34
+ cloud sso disable[/code] command to disable SSO.
35
+
36
+ [bold][underline]Examples[/underline][/bold]
37
+
38
+ - Enable the SSO configuration.
39
+ $ [dim]nextmv cloud sso enable[/dim]
40
+
41
+ - Enable the SSO configuration without confirmation prompt.
42
+ $ [dim]nextmv cloud sso enable --yes[/dim]
43
+ """
44
+
45
+ if not yes:
46
+ confirm = get_confirmation(
47
+ "Are you sure you want to enable the sso configuration?.",
48
+ )
49
+
50
+ if not confirm:
51
+ info("SSO configuration will not be enabled.")
52
+ return
53
+
54
+ sso_config = build_sso_config(profile)
55
+ sso_config.enable()
56
+ success("SSO configuration has been enabled.")
@@ -0,0 +1,61 @@
1
+ """
2
+ This module defines the cloud sso get command for the Nextmv CLI.
3
+ """
4
+
5
+ import json
6
+ from typing import Annotated
7
+
8
+ import typer
9
+
10
+ from nextmv.cli.configuration.config import build_client
11
+ from nextmv.cli.message import in_progress, print_json, success
12
+ from nextmv.cli.options import ProfileOption
13
+ from nextmv.cloud.sso import SSOConfiguration
14
+
15
+ # Set up subcommand application.
16
+ app = typer.Typer()
17
+
18
+
19
+ @app.command()
20
+ def get(
21
+ output: Annotated[
22
+ str | None,
23
+ typer.Option(
24
+ "--output",
25
+ "-o",
26
+ help="Saves the SSO configuration information to this location.",
27
+ metavar="OUTPUT_PATH",
28
+ ),
29
+ ] = None,
30
+ profile: ProfileOption = None,
31
+ ) -> None:
32
+ """
33
+ Get the information of a Nextmv Cloud SSO configuration.
34
+
35
+ This command is useful to get the attributes of an existing Nextmv Cloud
36
+ SSO configuration.
37
+
38
+ [bold][underline]Examples[/underline][/bold]
39
+
40
+ - Get the SSO configuration.
41
+ $ [dim]nextmv cloud sso get[/dim]
42
+
43
+ - Get the SSO configuration and save the information to an [magenta]sso_config.json[/magenta] file.
44
+ $ [dim]nextmv cloud sso get --output sso_config.json[/dim]
45
+ """
46
+
47
+ client = build_client(profile)
48
+ in_progress(msg="Getting SSO configuration...")
49
+
50
+ sso_config = SSOConfiguration.get(client)
51
+ sso_config_dict = sso_config.to_dict()
52
+
53
+ if output is not None and output != "":
54
+ with open(output, "w") as f:
55
+ json.dump(sso_config_dict, f, indent=2)
56
+
57
+ success(msg=f"SSO configuration information saved to [magenta]{output}[/magenta].")
58
+
59
+ return
60
+
61
+ print_json(sso_config_dict)
@@ -0,0 +1,78 @@
1
+ """
2
+ This module defines the cloud sso update command for the Nextmv CLI.
3
+ """
4
+
5
+ import json
6
+ from typing import Annotated
7
+
8
+ import typer
9
+
10
+ from nextmv.cli.configuration.config import build_sso_config
11
+ from nextmv.cli.message import print_json, success
12
+ from nextmv.cli.options import ProfileOption
13
+
14
+ # Set up subcommand application.
15
+ app = typer.Typer()
16
+
17
+
18
+ @app.command()
19
+ def update(
20
+ metadata_url: Annotated[
21
+ str | None,
22
+ typer.Option(
23
+ "--metadata-url",
24
+ "-u",
25
+ help="The URL to the SSO metadata document to update.",
26
+ metavar="METADATA_URL",
27
+ ),
28
+ ] = None,
29
+ metadata_document: Annotated[
30
+ str | None,
31
+ typer.Option(
32
+ "--metadata-document",
33
+ "-d",
34
+ help="The SSO metadata document as a string to update.",
35
+ metavar="METADATA_DOCUMENT",
36
+ ),
37
+ ] = None,
38
+ output: Annotated[
39
+ str | None,
40
+ typer.Option(
41
+ "--output",
42
+ "-o",
43
+ help="Saves the updated SSO configuration information to this location.",
44
+ metavar="OUTPUT_PATH",
45
+ ),
46
+ ] = None,
47
+ profile: ProfileOption = None,
48
+ ) -> None:
49
+ """
50
+ Updates information of a Nextmv Cloud SSO configuration.
51
+
52
+ This command allows you to update the metadata URL or metadata document of
53
+ an existing SSO configuration.
54
+
55
+ [bold][underline]Examples[/underline][/bold]
56
+
57
+ - Update the SSO configuration with a new metadata URL.
58
+ $ [dim]nextmv cloud sso update --metadata-url "https://example.com/metadata.xml"[/dim]
59
+
60
+ - Update the SSO configuration with a new metadata document and save the updated information to an
61
+ [magenta]updated_sso_config.json[/magenta] file.
62
+ $ [dim]nextmv cloud sso update --metadata-document "<xml>...</xml>" --output updated_sso_config.json[/dim]
63
+ """
64
+
65
+ sso_config = build_sso_config(profile)
66
+ updated_config = sso_config.update(metadata_url=metadata_url, metadata_document=metadata_document)
67
+ success("SSO configuration updated successfully.")
68
+ updated_config_dict = updated_config.to_dict()
69
+
70
+ if output is not None and output != "":
71
+ with open(output, "w") as f:
72
+ json.dump(updated_config_dict, f, indent=2)
73
+
74
+ success(msg=f"Updated SSO configuration information saved to [magenta]{output}[/magenta].")
75
+
76
+ return
77
+
78
+ print_json(updated_config_dict)
@@ -9,8 +9,8 @@ from nextmv.cli.community.list import app as list_app
9
9
 
10
10
  # Set up subcommand application.
11
11
  app = typer.Typer()
12
- app.add_typer(list_app)
13
12
  app.add_typer(clone_app)
13
+ app.add_typer(list_app)
14
14
 
15
15
 
16
16
  @app.callback()
@@ -12,6 +12,7 @@ from nextmv.cli.message import error, success, warning
12
12
  from nextmv.cloud.account import Account
13
13
  from nextmv.cloud.application import Application
14
14
  from nextmv.cloud.client import Client
15
+ from nextmv.cloud.sso import SSOConfiguration
15
16
 
16
17
  # Some useful constants.
17
18
  CONFIG_DIR = Path.home() / ".nextmv"
@@ -207,6 +208,32 @@ def build_account(account_id: str | None = None, profile: str | None = None) ->
207
208
  return Account(account_id=account_id, client=client)
208
209
 
209
210
 
211
+ def build_sso_config(profile: str | None = None) -> SSOConfiguration:
212
+ """
213
+ Builds a `cloud.SSOConfiguration` using the API key and endpoint for the given
214
+ profile. If no profile is given, the default profile is used.
215
+
216
+ Parameters
217
+ ----------
218
+ profile : str | None
219
+ The profile name to use. If None, the default profile is used.
220
+
221
+ Returns
222
+ -------
223
+ SSOConfiguration
224
+ An SSOConfiguration object for the configured profile.
225
+
226
+ Raises
227
+ ------
228
+ typer.Exit
229
+ If the configuration is invalid or missing.
230
+ """
231
+
232
+ client = build_client(profile)
233
+
234
+ return SSOConfiguration(client=client)
235
+
236
+
210
237
  def obscure_api_key(api_key: str) -> str:
211
238
  """
212
239
  Obscure an API key for display purposes.
nextmv/cloud/__init__.py CHANGED
@@ -61,6 +61,7 @@ from .shadow import StartEvents as StartEvents
61
61
  from .shadow import StopIntent as StopIntent
62
62
  from .shadow import TerminationEvents as TerminationEvents
63
63
  from .shadow import TestComparison as TestComparison
64
+ from .sso import SSOConfiguration as SSOConfiguration
64
65
  from .switchback import SwitchbackPlan as SwitchbackPlan
65
66
  from .switchback import SwitchbackPlanUnit as SwitchbackPlanUnit
66
67
  from .switchback import SwitchbackTest as SwitchbackTest
nextmv/cloud/account.py CHANGED
@@ -188,30 +188,32 @@ class Account(BaseModel):
188
188
 
189
189
  You can import the `Account` class directly from `cloud`:
190
190
 
191
- ```python
192
- from nextmv.cloud import Account
193
- ```
191
+ ```python from nextmv.cloud import Account ```
194
192
 
195
193
  This class provides access to account-level operations in the Nextmv Cloud,
196
194
  such as retrieving the queue of runs.
197
195
 
198
- Note: It is recommended to use `Account.get()` or `Account.new()`
199
- instead of direct initialization to ensure proper setup.
196
+ Note: It is recommended to use `Account.get()` or `Account.new()` instead
197
+ of direct initialization to ensure proper setup.
200
198
 
201
- Parameters
199
+ Attributes
202
200
  ----------
203
- client : Client
204
- Client to use for interacting with the Nextmv Cloud API.
205
201
  account_id : str, optional
206
202
  ID of the account (organization).
207
203
  name : str, optional
208
204
  Name of the account (organization).
209
205
  members : list[AccountMember], optional
210
206
  List of members in the account (organization).
207
+ client : Client
208
+ Client to use for interacting with the Nextmv Cloud API. This is an
209
+ SDK-specific attribute and it is not part of the API representation of
210
+ an account.
211
211
  account_endpoint : str, default="v1/account"
212
- Base endpoint for the account (SDK-specific).
212
+ Base endpoint for the account. This is an SDK-specific attribute and it
213
+ is not part of the API representation of an account.
213
214
  organization_endpoint : str, default="v1/organization/{organization_id}"
214
- Base endpoint for organization operations (SDK-specific).
215
+ Base endpoint for organization operations. This is an SDK-specific
216
+ attribute and it is not part of the API representation of an account.
215
217
 
216
218
  Examples
217
219
  --------
@@ -121,10 +121,8 @@ class Application(
121
121
  Note: It is recommended to use `Application.get()` or `Application.new()`
122
122
  instead of direct initialization to ensure proper setup.
123
123
 
124
- Parameters
124
+ Attributes
125
125
  ----------
126
- client : Client
127
- Client to use for interacting with the Nextmv Cloud API.
128
126
  id : str
129
127
  ID of the application.
130
128
  name : str, optional
@@ -145,12 +143,19 @@ class Application(
145
143
  Creation timestamp of the application.
146
144
  updated_at : datetime, optional
147
145
  Last update timestamp of the application.
146
+ client : Client
147
+ Client to use for interacting with the Nextmv Cloud API. This is an
148
+ SDK-specific attribute and it is not part of the API representation of
149
+ an application.
148
150
  endpoint : str, default="v1/applications/{id}"
149
- Base endpoint for the application (SDK-specific).
151
+ Base endpoint for the application. This is an SDK-specific attribute
152
+ and it is not part of the API representation of an application.
150
153
  experiments_endpoint : str, default="{base}/experiments"
151
- Base endpoint for experiments (SDK-specific).
154
+ Base endpoint for experiments. This is an SDK-specific attribute and it
155
+ is not part of the API representation of an application.
152
156
  ensembles_endpoint : str, default="{base}/ensembles"
153
- Base endpoint for ensembles (SDK-specific).
157
+ Base endpoint for ensembles. This is an SDK-specific attribute and it
158
+ is not part of the API representation of an application.
154
159
 
155
160
  Examples
156
161
  --------
nextmv/cloud/sso.py ADDED
@@ -0,0 +1,248 @@
1
+ """
2
+ Single Sign-On (SSO) functionality for the Nextmv Cloud API.
3
+
4
+ This module provides classes and methods to manage Single Sign-On (SSO)
5
+ configurations for Nextmv Cloud organizations (accounts).
6
+
7
+ Classes
8
+ -------
9
+ SSOConfiguration
10
+ Represents the SSO configuration for a Nextmv Cloud organization (account)
11
+ and provides methods to create, retrieve, update, enable, disable, and
12
+ delete SSO configurations.
13
+ """
14
+
15
+ from pydantic import Field
16
+
17
+ from nextmv.base_model import BaseModel
18
+ from nextmv.cloud.client import Client
19
+
20
+
21
+ class SSOConfiguration(BaseModel):
22
+ """
23
+ Configuration for Single Sign-On (SSO) in Nextmv Cloud.
24
+
25
+ You can import the `SSOConfiguration` class directly from `cloud`:
26
+
27
+ ```python
28
+ from nextmv.cloud import SSOConfiguration
29
+ ```
30
+
31
+ Attributes
32
+ ----------
33
+ allow_non_domain_users : bool, optional
34
+ Whether to allow users who are not part of the SSO domain to access the
35
+ Nextmv Cloud organization (account). Default is `False`.
36
+ enabled : bool, optional
37
+ Whether SSO is enabled for the Nextmv Cloud organization (account).
38
+ metadata_url : str, optional
39
+ The URL to the SSO metadata document.
40
+ metadata_document : str, optional
41
+ The SSO metadata document as a string.
42
+ client : Client
43
+ Client to use for interacting with the Nextmv Cloud API. This is an
44
+ SDK-specific attribute and it is not part of the API representation of
45
+ an SSO configuration.
46
+ sso_endpoint : str
47
+ Base endpoint for SSO operations. This is an SDK-specific attribute and
48
+ it is not part of the API representation of an SSO configuration.
49
+ """
50
+
51
+ allow_non_domain_users: bool = False
52
+ """
53
+ Whether to allow users who are not part of the SSO domain to access the
54
+ Nextmv Cloud organization (account).
55
+ """
56
+
57
+ enabled: bool | None = None
58
+ """
59
+ Whether SSO is enabled for the Nextmv Cloud organization (account).
60
+ """
61
+ metadata_url: str | None = None
62
+ """
63
+ The URL to the SSO metadata document.
64
+ """
65
+ metadata_document: str | None = None
66
+ """
67
+ The SSO metadata document as a string.
68
+ """
69
+
70
+ # SDK-specific attributes for convenience when using methods.
71
+ client: Client = Field(exclude=True)
72
+ """Client to use for interacting with the Nextmv Cloud API."""
73
+ sso_endpoint: str = Field(exclude=True, default="/v1/enterprise/sso")
74
+
75
+ @classmethod
76
+ def get(cls, client: Client) -> "SSOConfiguration":
77
+ """
78
+ Retrieve the SSO configuration for the current Nextmv Cloud
79
+ organization (account).
80
+
81
+ Parameters
82
+ ----------
83
+ client : Client
84
+ Client to use for interacting with the Nextmv Cloud API.
85
+
86
+ Returns
87
+ -------
88
+ SSOConfiguration
89
+ The SSO configuration for the organization (account).
90
+
91
+ Raises
92
+ ------
93
+ requests.HTTPError
94
+ If the response status code is not 2xx.
95
+ """
96
+
97
+ response = client.request(
98
+ method="GET",
99
+ endpoint=cls.sso_endpoint,
100
+ )
101
+
102
+ return cls.from_dict({"client": client} | response.json())
103
+
104
+ @classmethod
105
+ def new(
106
+ cls,
107
+ client: Client,
108
+ allow_non_domain_users: bool = False,
109
+ enabled: bool | None = None,
110
+ metadata_url: str | None = None,
111
+ metadata_document: str | None = None,
112
+ ) -> "SSOConfiguration":
113
+ """
114
+ Create a new SSO configuration for the current Nextmv Cloud
115
+ organization (account).
116
+
117
+ Parameters
118
+ ----------
119
+ client : Client
120
+ Client to use for interacting with the Nextmv Cloud API.
121
+ allow_non_domain_users : bool, optional
122
+ Whether to allow users who are not part of the SSO domain to access
123
+ the Nextmv Cloud organization (account). Default is `False`.
124
+ enabled : bool, optional
125
+ Whether SSO is enabled for the Nextmv Cloud organization (account).
126
+ metadata_url : str, optional
127
+ The URL to the SSO metadata document.
128
+ metadata_document : str, optional
129
+ The SSO metadata document as a string.
130
+
131
+ Returns
132
+ -------
133
+ SSOConfiguration
134
+ The newly created SSO configuration for the organization (account).
135
+
136
+ Raises
137
+ ------
138
+ requests.HTTPError
139
+ If the response status code is not 2xx.
140
+ """
141
+
142
+ payload = {
143
+ "allow_non_domain_users": allow_non_domain_users,
144
+ "enabled": enabled,
145
+ "metadata_url": metadata_url,
146
+ "metadata_document": metadata_document,
147
+ }
148
+
149
+ response = client.request(
150
+ method="POST",
151
+ endpoint=cls.sso_endpoint,
152
+ json=payload,
153
+ )
154
+
155
+ return cls.from_dict({"client": client} | response.json())
156
+
157
+ def delete(self) -> None:
158
+ """
159
+ Delete the SSO configuration for the current Nextmv Cloud
160
+ organization (account).
161
+
162
+ Raises
163
+ ------
164
+ requests.HTTPError
165
+ If the response status code is not 2xx.
166
+ """
167
+
168
+ self.client.request(
169
+ method="DELETE",
170
+ endpoint=self.sso_endpoint,
171
+ )
172
+
173
+ def disable(self) -> None:
174
+ """
175
+ Disable SSO for the current Nextmv Cloud organization (account).
176
+
177
+ Raises
178
+ ------
179
+ requests.HTTPError
180
+ If the response status code is not 2xx.
181
+ """
182
+
183
+ self.client.request(
184
+ method="PUT",
185
+ endpoint=f"{self.sso_endpoint}/disable",
186
+ )
187
+
188
+ def enable(self) -> None:
189
+ """
190
+ Enable SSO for the current Nextmv Cloud organization (account).
191
+
192
+ Raises
193
+ ------
194
+ requests.HTTPError
195
+ If the response status code is not 2xx.
196
+ """
197
+
198
+ self.client.request(
199
+ method="PUT",
200
+ endpoint=f"{self.sso_endpoint}/enable",
201
+ )
202
+
203
+ def update(
204
+ self,
205
+ metadata_url: str | None = None,
206
+ metadata_document: str | None = None,
207
+ ) -> "SSOConfiguration":
208
+ """
209
+ Update the SSO configuration for the current Nextmv Cloud
210
+ organization (account).
211
+
212
+ If you wish to enable or disable SSO, please use the `enable` and
213
+ `disable` methods instead.
214
+
215
+ Parameters
216
+ ----------
217
+ metadata_url : str, optional
218
+ The URL to the SSO metadata document.
219
+ metadata_document : str, optional
220
+ The SSO metadata document as a string.
221
+
222
+ Returns
223
+ -------
224
+ SSOConfiguration
225
+ The updated SSO configuration for the organization (account).
226
+
227
+ Raises
228
+ ------
229
+ requests.HTTPError
230
+ If the response status code is not 2xx.
231
+ """
232
+
233
+ config = self.get(self.client)
234
+ config_dict = config.to_dict()
235
+ payload = config_dict.copy()
236
+
237
+ if metadata_url is not None and metadata_url != "":
238
+ payload["metadata_url"] = metadata_url
239
+ if metadata_document is not None and metadata_document != "":
240
+ payload["metadata_document"] = metadata_document
241
+
242
+ response = self.client.request(
243
+ method="PUT",
244
+ endpoint=self.sso_endpoint,
245
+ json=payload,
246
+ )
247
+
248
+ return self.from_dict({"client": self.client} | response.json())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextmv
3
- Version: 1.0.0.dev10
3
+ Version: 1.1.0.dev0
4
4
  Summary: The all-purpose Python SDK for Nextmv
5
5
  Project-URL: Homepage, https://www.nextmv.io
6
6
  Project-URL: Documentation, https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
@@ -1,4 +1,4 @@
1
- nextmv/__about__.py,sha256=OuA1Ew1qq7c4njml2fR_IWNXf8n-DPf1oa_Nfx93r5E,29
1
+ nextmv/__about__.py,sha256=sdMWpxPaxLx9snT2SjJ_Sjn3ddOnm-EdMGcDpyW0Zu0,28
2
2
  nextmv/__entrypoint__.py,sha256=XMT-ds1f2Yc6KoI2C0YEH-rJj5gVLfJMqUdRfcA3_KQ,1070
3
3
  nextmv/__init__.py,sha256=LwpGBSiV0UG13zKHO2N3Ikb7bCMV08Gfbl6Cp80b_2g,3813
4
4
  nextmv/_serialization.py,sha256=jYitMS1MU8ldsmObT-K_8V8P2Wx69tnDiEHCCgPGun4,2834
@@ -21,15 +21,15 @@ nextmv/cli/main.py,sha256=AwkIavXOAY-WmLA7F9eY2o6RWTOYHhgZiLs6WeqcB2E,5518
21
21
  nextmv/cli/message.py,sha256=NWeCmpkA_IEDay3Fu3YjNN9eSi3p8e-Tw9wp1qAjfXI,3809
22
22
  nextmv/cli/options.py,sha256=ymd6Y7_ZQkln35nHw3pLnFpqivgmJfuYAnyizmEuonc,6887
23
23
  nextmv/cli/version.py,sha256=VRbfNpUvCFYPcphr-F3Ph4Z4UwtVis4keyVFHj1JISw,681
24
- nextmv/cli/cloud/__init__.py,sha256=pywNNBy_poHaKn3_oIZRR9DDE8w3u65KvLpnX6S0BQI,1886
24
+ nextmv/cli/cloud/__init__.py,sha256=0Ec_ettl3cHcLt_tgH6z1M1HGtADxdHLUBBwvmCj4rA,1969
25
25
  nextmv/cli/cloud/acceptance/__init__.py,sha256=v4U1m6z5zI8mQpmIE4kFeEYOsaDxnGRnRj2j5I6WueI,711
26
26
  nextmv/cli/cloud/acceptance/create.py,sha256=Mtiy7fMBU5Ay_hxb2DXxdaM2XvR_QDbldtyjQIAaelQ,14582
27
27
  nextmv/cli/cloud/acceptance/delete.py,sha256=htN7XqGudKhSrDpUwWhcb5VUp-sf4PTRZpqf5ObzAg8,2193
28
28
  nextmv/cli/cloud/acceptance/get.py,sha256=pb3hRdIiynTi4K7xDNCMJE7bW46FE-X3EoAQU8kQJjE,3438
29
29
  nextmv/cli/cloud/acceptance/list.py,sha256=9tTV4B2lgDqNxDnaNXkHxeh7jUQuAu9GQJsEKJ_NqIo,1881
30
30
  nextmv/cli/cloud/acceptance/update.py,sha256=ZyhYlkA7Sp0WWMewV774elwvjFKhyg-7jIE9L1yeipU,2912
31
- nextmv/cli/cloud/account/__init__.py,sha256=N3WqUHe48tBFWQ_I83EAgL_ng-y0tN6qHKROIMMxQhE,768
32
- nextmv/cli/cloud/account/create.py,sha256=V8f2zlGryBHKR3TBI3A7t9MSSaS8GHMClYquGQXqRrQ,2876
31
+ nextmv/cli/cloud/account/__init__.py,sha256=-jKD2vNYCs1RKmJ5LmgYE8jnmwKnvCBPVeHSdNFkHx0,882
32
+ nextmv/cli/cloud/account/create.py,sha256=D1jeUrPUgcWx4NnqxIJyI9hVkVa46k0tbGjSumfyWWw,3002
33
33
  nextmv/cli/cloud/account/delete.py,sha256=G6vblaHK21goNPIGRnTQyLDpZuPvRdMa5QEsZ566hF8,1828
34
34
  nextmv/cli/cloud/account/get.py,sha256=KT0Cs2ZQtZV4D0efAjMIj47RSKSSsU3-1ZApH8oYzLU,1860
35
35
  nextmv/cli/cloud/account/update.py,sha256=z_g_uEAgBJDcb0Kh80NbKTA7gycrJb6hHjJPVG9wEVw,2124
@@ -106,6 +106,13 @@ nextmv/cli/cloud/shadow/metadata.py,sha256=vHJYVDXXHwiqQrG0J0D_aRP--b47UfEgJwJOX
106
106
  nextmv/cli/cloud/shadow/start.py,sha256=SkDYSfyQLdfHJKCOzc4CW6MVO7YBWCZCOAoGBzqSFhI,1464
107
107
  nextmv/cli/cloud/shadow/stop.py,sha256=WNg73nHkQ6Mo7hdg3qfSXQBkd77iKPfRIdSSJxTHhTY,1706
108
108
  nextmv/cli/cloud/shadow/update.py,sha256=l7_gODO9fXYGOLzFMJmIVpT5Jku9XQAo2PI5x3AP4xU,2880
109
+ nextmv/cli/cloud/sso/__init__.py,sha256=30jM1Qh9L1fQIctcnT5xcHUggismEYsIhHIsxgrI4_I,919
110
+ nextmv/cli/cloud/sso/create.py,sha256=bF04XZ-dEFsDEsVIjVtMNP3UH83x5XyLA6vt8ITuNbg,3325
111
+ nextmv/cli/cloud/sso/delete.py,sha256=5mB9t8UcHTuN8WEPbrJG93Ai9uGXOzfInK7fb_IL8pc,1563
112
+ nextmv/cli/cloud/sso/disable.py,sha256=Juv6xC6qMlQrG_C_c-s7V4FqepPzbueKifNeX6RwZ0w,1464
113
+ nextmv/cli/cloud/sso/enable.py,sha256=OH2Yyz8RHhYDNG4o2ABT23k4Hdd9iBnJTbf8JVq7mf4,1451
114
+ nextmv/cli/cloud/sso/get.py,sha256=odfcoggvMOgDT9VUtji-wUMysCEgaHnqjAsrVr1SmMk,1644
115
+ nextmv/cli/cloud/sso/update.py,sha256=u4Z_Ejr0612EXwvBVJZpJA_p6PP763BNUXCuQTNp_yY,2404
109
116
  nextmv/cli/cloud/switchback/__init__.py,sha256=jYeujjbqvqRGIgvC0wr3I6zavw1az7IS8jiJsAlH-z4,981
110
117
  nextmv/cli/cloud/switchback/create.py,sha256=lEboNjN1ZFbuOCFmK2ADIRH-pIENc80NcR809rDOY3I,5085
111
118
  nextmv/cli/cloud/switchback/delete.py,sha256=W0TWsYw0MI23MbN8Oj6lQn7K7jEafY1dWW4HVMooyeY,2186
@@ -124,17 +131,17 @@ nextmv/cli/cloud/version/exists.py,sha256=DAWP-3n_yaqqxtQAWBwhSziMYJifFEdydfOmsv
124
131
  nextmv/cli/cloud/version/get.py,sha256=eGbka3TG8UJE150h22rn0BUqTi1xRE7roVDj6yJvnRY,1839
125
132
  nextmv/cli/cloud/version/list.py,sha256=sKdHgyowLG1jyUEtu87yCPC5_2-0i3VDEgfmvb-bBn0,1770
126
133
  nextmv/cli/cloud/version/update.py,sha256=mEUYXGHLGkiEGH31KK6jDDfviHEhVCdLjLQL_5u0vLk,2869
127
- nextmv/cli/community/__init__.py,sha256=t2l6adm9Km6hSvSFzeKHTQzacVSnwjx4wpj2kqee5nM,612
134
+ nextmv/cli/community/__init__.py,sha256=FJRlBlIC4y-npgh9HNz2wezecq8vfsYWo2MAQdUj1UM,612
128
135
  nextmv/cli/community/clone.py,sha256=_I1C58pKmfAHdl-8eaZDeaxZm2Rnp2en8PCPdflAse4,2912
129
136
  nextmv/cli/community/list.py,sha256=Gf9E-wD-0GQcaTPGBNp8p_zX44UAL5bYG6LKroTKLCU,5807
130
137
  nextmv/cli/configuration/__init__.py,sha256=7oryF4PKkORh8bcdgbN2k36rZrFpJsM7Xfq_J4-MkFs,516
131
- nextmv/cli/configuration/config.py,sha256=t43ubCcbfbpfq9HvkVb2WQY9V47lrLEP0KvsWfjOJ8Y,6667
138
+ nextmv/cli/configuration/config.py,sha256=6NM537xHrmUruFRtrXkhE3OI0XFRAnCaSJDEfG_AtHw,7356
132
139
  nextmv/cli/configuration/create.py,sha256=lTOxE-38BO7qed1I-wlJ8Ey1WHGMTPbGMozncW8xizM,2737
133
140
  nextmv/cli/configuration/delete.py,sha256=-3IL0nh367D0NhIdPXOCCCAWhejABS8QIfOcoH_cW-M,1915
134
141
  nextmv/cli/configuration/list.py,sha256=HIZvDJQW5B0-o_ZqQHuxRw7N_VmxqYM46fucKCvo1zw,2208
135
- nextmv/cloud/__init__.py,sha256=IW9fdg3QgusJGAU4VVEu5qkCidzalyYf4wjC1T14rnQ,4183
142
+ nextmv/cloud/__init__.py,sha256=8zrGJ-UYusPgBz87CnUNEteiU-V475EOFStGPQWFNYY,4237
136
143
  nextmv/cloud/acceptance_test.py,sha256=H34lvccJzN1URpnhrHstcVxgvq1s2iCymiKIPBHcToY,25828
137
- nextmv/cloud/account.py,sha256=X2xQjzhgEdKR0eypH8lWKUOwDISjJSd5SwOwEnpfTVk,13573
144
+ nextmv/cloud/account.py,sha256=y1fNj7Y1ghQ3r9nIkpSFlmsTsCaN1ZzOfEOHkjavvoE,13849
138
145
  nextmv/cloud/assets.py,sha256=alw634ub-DR0CHQXZy_ObeGvQthPXFLdgzgbvbH1SGY,1376
139
146
  nextmv/cloud/batch_experiment.py,sha256=flwP5pbBio-ilAbopj8DdSWOlxGbct1IOElsgcyVN8U,10545
140
147
  nextmv/cloud/client.py,sha256=Yj4FE4GKsLHkYijAYXcotlyNfhAWANMuWetHXsYPg1M,18101
@@ -147,10 +154,11 @@ nextmv/cloud/package.py,sha256=88XSJ15QGcHboNJAw2hGowiLKBu2O2nV5ZieZFx7XDI,17133
147
154
  nextmv/cloud/scenario.py,sha256=1_4PI9ehYaSonEe_l59cFhZNmqQ_brXXP6-mVq9i8a8,14183
148
155
  nextmv/cloud/secrets.py,sha256=fA5cX0jfTsPVZWV7433wzETGlXpWRLHGswuObx9e6FQ,6820
149
156
  nextmv/cloud/shadow.py,sha256=U-s9alkDS3wmYCEVDKEvuceveWOZOiF7rkH4_8eKdNk,7711
157
+ nextmv/cloud/sso.py,sha256=FaLE-e-xMrbXgTJbD-Mti4knroGWU4XGroZKPRCJsWk,7325
150
158
  nextmv/cloud/switchback.py,sha256=6e4J5zCewgGaitB5iJiO3u6BPHcAlzdAB5WU8j2b4K8,7427
151
159
  nextmv/cloud/url.py,sha256=Fz70ywkWdCLmP21ZBmJwZi5kDbjpmsX_VlwVF_xQeHg,1836
152
160
  nextmv/cloud/version.py,sha256=5_S7_pWUVBFbvAArku20eK7S645GJcHtgE2OpXLdSzQ,5300
153
- nextmv/cloud/application/__init__.py,sha256=x9khEFlWUdupBxzMuSyrCftopNtrK64LTTEaCRSRwyM,32712
161
+ nextmv/cloud/application/__init__.py,sha256=_f8AKvw3VY5d8MtM1JMao6kbVafZWiLi7cKJilzP0ik,33099
154
162
  nextmv/cloud/application/_acceptance.py,sha256=PEkf9cDunK40UNw96QBhpJpH5SOFLZMtmnyX84uAo9k,13974
155
163
  nextmv/cloud/application/_batch_scenario.py,sha256=cSsX5vPOkm91UqRBPIcqlOvQ0iojwt4sQKYGZEE7x6k,28479
156
164
  nextmv/cloud/application/_ensemble.py,sha256=05l9uR0hTnW8nQjhRzjd2TPfvCoaAqNddWP-aVRL5rg,7666
@@ -178,8 +186,8 @@ nextmv/local/geojson_handler.py,sha256=7FavJdkUonop-yskjis0x3qFGB8A5wZyoBUblw-bV
178
186
  nextmv/local/local.py,sha256=cp56UpI8h19Ob6Jvb_Ni0ceXH5Vv3ET_iPTDe6ftq3Y,2617
179
187
  nextmv/local/plotly_handler.py,sha256=bLb50e3AkVr_W-F6S7lXfeRdN60mG2jk3UElNmhoMWU,1930
180
188
  nextmv/local/runner.py,sha256=bM1dFIAG4f9pEtbyevzkRa9nSppqTeD8naomNzJVBRU,8560
181
- nextmv-1.0.0.dev10.dist-info/METADATA,sha256=La1768YqfIVx_d8aYji252SX5eDvYEHS7CkloJwIGoc,16526
182
- nextmv-1.0.0.dev10.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
183
- nextmv-1.0.0.dev10.dist-info/entry_points.txt,sha256=bH7kXUt_IOLpeW_O7Z-J2gALs2YYJ4CmWuzS8MdK6uY,48
184
- nextmv-1.0.0.dev10.dist-info/licenses/LICENSE,sha256=ZIbK-sSWA-OZprjNbmJAglYRtl5_K4l9UwAV3PGJAPc,11349
185
- nextmv-1.0.0.dev10.dist-info/RECORD,,
189
+ nextmv-1.1.0.dev0.dist-info/METADATA,sha256=PBdBO9bnlZQoMLvyHFiEfoErbhGp3EKZzOMZ9e5TwIw,16525
190
+ nextmv-1.1.0.dev0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
191
+ nextmv-1.1.0.dev0.dist-info/entry_points.txt,sha256=bH7kXUt_IOLpeW_O7Z-J2gALs2YYJ4CmWuzS8MdK6uY,48
192
+ nextmv-1.1.0.dev0.dist-info/licenses/LICENSE,sha256=ZIbK-sSWA-OZprjNbmJAglYRtl5_K4l9UwAV3PGJAPc,11349
193
+ nextmv-1.1.0.dev0.dist-info/RECORD,,