diff --git a/Cargo.lock b/Cargo.lock index 219fce9c..11cdc71c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "config" -version = "0.3.55" +version = "0.3.56" dependencies = [ "base64", "chrono", @@ -598,7 +598,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto" -version = "0.3.55" +version = "0.3.56" dependencies = [ "aes-gcm", "base64", @@ -3316,7 +3316,7 @@ dependencies = [ [[package]] name = "testutils" -version = "0.3.55" +version = "0.3.56" dependencies = [ "pem", "rsa", @@ -3586,7 +3586,7 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" -version = "0.3.55" +version = "0.3.56" dependencies = [ "config", "pyo3", @@ -3614,7 +3614,7 @@ dependencies = [ [[package]] name = "tower-api" -version = "0.3.55" +version = "0.3.56" dependencies = [ "reqwest", "serde", @@ -3626,7 +3626,7 @@ dependencies = [ [[package]] name = "tower-cmd" -version = "0.3.55" +version = "0.3.56" dependencies = [ "axum", "bytes", @@ -3696,7 +3696,7 @@ checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-package" -version = "0.3.55" +version = "0.3.56" dependencies = [ "async-compression", "config", @@ -3714,7 +3714,7 @@ dependencies = [ [[package]] name = "tower-runtime" -version = "0.3.55" +version = "0.3.56" dependencies = [ "async-trait", "chrono", @@ -3737,7 +3737,7 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tower-telemetry" -version = "0.3.55" +version = "0.3.56" dependencies = [ "tracing", "tracing-appender", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "tower-uv" -version = "0.3.55" +version = "0.3.56" dependencies = [ "async-compression", "async_zip", @@ -3764,7 +3764,7 @@ dependencies = [ [[package]] name = "tower-version" -version = "0.3.55" +version = "0.3.56" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 95351386..a9b016d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] edition = "2021" -version = "0.3.55" +version = "0.3.56" description = "Tower is the best way to host Python data apps in production" rust-version = "1.81" authors = ["Brad Heller "] diff --git a/crates/config/src/error.rs b/crates/config/src/error.rs index a74e3add..53589af2 100644 --- a/crates/config/src/error.rs +++ b/crates/config/src/error.rs @@ -9,6 +9,9 @@ pub enum Error { #[snafu(display("No home directory found"))] NoHomeDir, + #[snafu(display("IO error: {}", source))] + Io { source: std::io::Error }, + #[snafu(display("No session file found"))] NoSession, @@ -33,8 +36,8 @@ pub enum Error { } impl From for Error { - fn from(_: std::io::Error) -> Self { - Error::ConfigDirNotFound + fn from(source: std::io::Error) -> Self { + Error::Io { source } } } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index a923147e..ca01b55f 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use tower_api::apis::configuration::Configuration; +use tower_api::apis::configuration::{ApiKey, Configuration}; use url::Url; mod error; @@ -9,7 +9,7 @@ mod towerfile; pub use error::Error; pub use session::{default_tower_url, Session, Team, Token, User}; -pub use towerfile::Towerfile; +pub use towerfile::{Parameter, Towerfile}; pub use session::{get_last_version_check_timestamp, set_last_version_check_timestamp}; @@ -22,6 +22,9 @@ pub struct Config { #[serde(skip_serializing, skip_deserializing)] pub session: Option, + #[serde(skip_serializing, skip_deserializing)] + pub api_key: Option, + // cache_dir is the directory that we should cache uv artifacts within. pub cache_dir: Option, } @@ -33,6 +36,7 @@ impl Config { tower_url: default_tower_url(), json: false, session: None, + api_key: None, cache_dir: Some(default_cache_dir()), } } @@ -44,12 +48,14 @@ impl Config { } else { default_tower_url() }; + let api_key = std::env::var("TOWER_API_KEY").ok(); Self { debug, tower_url, json: false, session: None, + api_key, cache_dir: Some(default_cache_dir()), } } @@ -78,6 +84,7 @@ impl Config { tower_url: sess.tower_url.clone(), json: self.json, session: Some(sess), + api_key: self.api_key, cache_dir: Some(default_cache_dir()), } } @@ -181,6 +188,15 @@ impl Config { configuration.base_path = base_path.to_string(); + // API key takes precedence over session-based auth + if let Some(ref key) = self.api_key { + configuration.api_key = Some(ApiKey { + prefix: None, + key: key.clone(), + }); + return configuration; + } + // Always read from disk to pick up team switches if let Ok(session) = Session::from_config_dir() { if let Some(active_team) = &session.active_team { diff --git a/crates/config/src/towerfile.rs b/crates/config/src/towerfile.rs index 703c999d..b0ab1d3c 100644 --- a/crates/config/src/towerfile.rs +++ b/crates/config/src/towerfile.rs @@ -119,14 +119,21 @@ impl Towerfile { Ok(()) } - /// add_parameter adds a new parameter to the Towerfile - pub fn add_parameter(&mut self, name: String, description: String, default: String) { - self.parameters.push(Parameter { - name, - description, - default, - hidden: false, - }); + /// set_parameter upserts a parameter by lookup name. If a parameter with the given name + /// exists, it is replaced. Otherwise, the parameter is appended. + pub fn set_parameter(&mut self, lookup_name: &str, param: Parameter) { + if let Some(existing) = self.parameters.iter_mut().find(|p| p.name == lookup_name) { + *existing = param; + } else { + self.parameters.push(param); + } + } + + /// remove_parameter removes a parameter by name, returning true if it was found + pub fn remove_parameter(&mut self, name: &str) -> bool { + let len_before = self.parameters.len(); + self.parameters.retain(|p| p.name != name); + self.parameters.len() < len_before } } @@ -299,20 +306,48 @@ mod test { } #[test] - fn test_add_parameter() { + fn test_set_parameter() { let mut towerfile = crate::Towerfile::default(); assert_eq!(towerfile.parameters.len(), 0); - towerfile.add_parameter( - "test-param".to_string(), - "A test parameter".to_string(), - "default-value".to_string(), - ); + towerfile.set_parameter("test-param", crate::Parameter { + name: "test-param".to_string(), + description: "A test parameter".to_string(), + default: "default-value".to_string(), + hidden: false, + }); assert_eq!(towerfile.parameters.len(), 1); assert_eq!(towerfile.parameters[0].name, "test-param"); assert_eq!(towerfile.parameters[0].description, "A test parameter"); assert_eq!(towerfile.parameters[0].default, "default-value"); + assert!(!towerfile.parameters[0].hidden); + + // upsert should replace, not duplicate + towerfile.set_parameter("test-param", crate::Parameter { + name: "test-param".to_string(), + description: "Updated".to_string(), + default: "new-value".to_string(), + hidden: false, + }); + + assert_eq!(towerfile.parameters.len(), 1); + assert_eq!(towerfile.parameters[0].description, "Updated"); + } + + #[test] + fn test_remove_parameter() { + let mut towerfile = crate::Towerfile::default(); + towerfile.set_parameter("param1", crate::Parameter { + name: "param1".to_string(), + description: "".to_string(), + default: "".to_string(), + hidden: false, + }); + + assert!(towerfile.remove_parameter("param1")); + assert_eq!(towerfile.parameters.len(), 0); + assert!(!towerfile.remove_parameter("param1")); } #[test] diff --git a/crates/tower-api/README.md b/crates/tower-api/README.md index 52a695e0..56afc877 100644 --- a/crates/tower-api/README.md +++ b/crates/tower-api/README.md @@ -8,7 +8,7 @@ For more information, please visit [https://tower.dev](https://tower.dev) This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://openapis.org) from a remote server, you can easily generate an API client. -- API version: v0.9.29 +- API version: v0.10.15 - Package version: 1.0.0 - Generator version: 7.19.0 - Build package: `org.openapitools.codegen.languages.RustClientCodegen` @@ -40,6 +40,7 @@ Class | Method | HTTP request | Description *DefaultApi* | [**create_catalog**](docs/DefaultApi.md#create_catalog) | **POST** /catalogs | Create catalog *DefaultApi* | [**create_device_login_ticket**](docs/DefaultApi.md#create_device_login_ticket) | **GET** /login/device | Create device login ticket *DefaultApi* | [**create_environment**](docs/DefaultApi.md#create_environment) | **POST** /environments | Create environment +*DefaultApi* | [**create_guest**](docs/DefaultApi.md#create_guest) | **POST** /guests | Create guest *DefaultApi* | [**create_password_reset**](docs/DefaultApi.md#create_password_reset) | **POST** /accounts/password-reset | Create password reset *DefaultApi* | [**create_sandbox_secrets**](docs/DefaultApi.md#create_sandbox_secrets) | **POST** /sandbox/secrets | Create Tower-provided sandbox secrets *DefaultApi* | [**create_schedule**](docs/DefaultApi.md#create_schedule) | **POST** /schedules | Create schedule @@ -53,6 +54,7 @@ Class | Method | HTTP request | Description *DefaultApi* | [**delete_app**](docs/DefaultApi.md#delete_app) | **DELETE** /apps/{name} | Delete app *DefaultApi* | [**delete_authenticator**](docs/DefaultApi.md#delete_authenticator) | **DELETE** /authenticators | Delete authenticator *DefaultApi* | [**delete_catalog**](docs/DefaultApi.md#delete_catalog) | **DELETE** /catalogs/{name} | Delete catalog +*DefaultApi* | [**delete_guest**](docs/DefaultApi.md#delete_guest) | **DELETE** /guests/{guest_id} | Delete guest *DefaultApi* | [**delete_schedule**](docs/DefaultApi.md#delete_schedule) | **DELETE** /schedules | Delete schedule *DefaultApi* | [**delete_secret**](docs/DefaultApi.md#delete_secret) | **DELETE** /secrets/{name} | Delete secret *DefaultApi* | [**delete_session**](docs/DefaultApi.md#delete_session) | **DELETE** /session | Delete session @@ -64,8 +66,10 @@ Class | Method | HTTP request | Description *DefaultApi* | [**describe_app**](docs/DefaultApi.md#describe_app) | **GET** /apps/{name} | Describe app *DefaultApi* | [**describe_app_version**](docs/DefaultApi.md#describe_app_version) | **GET** /apps/{name}/versions/{num} | Describe app version *DefaultApi* | [**describe_authentication_context**](docs/DefaultApi.md#describe_authentication_context) | **GET** /user/auth-context | Describe authentication context +*DefaultApi* | [**describe_catalog**](docs/DefaultApi.md#describe_catalog) | **GET** /catalogs/{name} | Describe catalog *DefaultApi* | [**describe_device_login_session**](docs/DefaultApi.md#describe_device_login_session) | **GET** /login/device/{device_code} | Describe device login session *DefaultApi* | [**describe_email_preferences**](docs/DefaultApi.md#describe_email_preferences) | **GET** /user/email-preferences | Describe email preferences +*DefaultApi* | [**describe_organization_usage**](docs/DefaultApi.md#describe_organization_usage) | **GET** /usage | Describe organization usage *DefaultApi* | [**describe_plan**](docs/DefaultApi.md#describe_plan) | **GET** /plan | Describe plan *DefaultApi* | [**describe_run**](docs/DefaultApi.md#describe_run) | **GET** /apps/{name}/runs/{seq} | Describe run *DefaultApi* | [**describe_run_graph**](docs/DefaultApi.md#describe_run_graph) | **GET** /apps/{name}/runs/{seq}/graph | Describe run graph @@ -90,6 +94,7 @@ Class | Method | HTTP request | Description *DefaultApi* | [**list_authenticators**](docs/DefaultApi.md#list_authenticators) | **GET** /authenticators | List authenticators *DefaultApi* | [**list_catalogs**](docs/DefaultApi.md#list_catalogs) | **GET** /catalogs | List catalogs *DefaultApi* | [**list_environments**](docs/DefaultApi.md#list_environments) | **GET** /environments | List environments +*DefaultApi* | [**list_guests**](docs/DefaultApi.md#list_guests) | **GET** /guests | List guests *DefaultApi* | [**list_my_team_invitations**](docs/DefaultApi.md#list_my_team_invitations) | **GET** /team-invites | List my team invitations *DefaultApi* | [**list_runners**](docs/DefaultApi.md#list_runners) | **GET** /runners | List runners *DefaultApi* | [**list_runs**](docs/DefaultApi.md#list_runs) | **GET** /apps/{name}/runs | List runs @@ -101,6 +106,7 @@ Class | Method | HTTP request | Description *DefaultApi* | [**list_teams**](docs/DefaultApi.md#list_teams) | **GET** /teams | List teams *DefaultApi* | [**list_webhooks**](docs/DefaultApi.md#list_webhooks) | **GET** /webhooks | List webhooks *DefaultApi* | [**refresh_session**](docs/DefaultApi.md#refresh_session) | **POST** /session/refresh | Refresh session +*DefaultApi* | [**regenerate_guest_login_url**](docs/DefaultApi.md#regenerate_guest_login_url) | **POST** /guests/{guest_id}/login-url | Regenerate guest login URL *DefaultApi* | [**remove_team_member**](docs/DefaultApi.md#remove_team_member) | **DELETE** /teams/{name}/members | Remove team member *DefaultApi* | [**resend_email_verification**](docs/DefaultApi.md#resend_email_verification) | **POST** /user/resend-verification | Resent email verification *DefaultApi* | [**resend_team_invitation**](docs/DefaultApi.md#resend_team_invitation) | **POST** /teams/{name}/invites/resend | Resend team invitation @@ -161,6 +167,8 @@ Class | Method | HTTP request | Description - [CreateDeviceLoginTicketResponse](docs/CreateDeviceLoginTicketResponse.md) - [CreateEnvironmentParams](docs/CreateEnvironmentParams.md) - [CreateEnvironmentResponse](docs/CreateEnvironmentResponse.md) + - [CreateGuestParams](docs/CreateGuestParams.md) + - [CreateGuestResponse](docs/CreateGuestResponse.md) - [CreatePasswordResetParams](docs/CreatePasswordResetParams.md) - [CreatePasswordResetResponse](docs/CreatePasswordResetResponse.md) - [CreateSandboxSecretsParams](docs/CreateSandboxSecretsParams.md) @@ -181,6 +189,7 @@ Class | Method | HTTP request | Description - [DeleteAuthenticatorParams](docs/DeleteAuthenticatorParams.md) - [DeleteAuthenticatorResponse](docs/DeleteAuthenticatorResponse.md) - [DeleteCatalogResponse](docs/DeleteCatalogResponse.md) + - [DeleteGuestOutputBody](docs/DeleteGuestOutputBody.md) - [DeleteScheduleParams](docs/DeleteScheduleParams.md) - [DeleteScheduleResponse](docs/DeleteScheduleResponse.md) - [DeleteSecretResponse](docs/DeleteSecretResponse.md) @@ -197,6 +206,7 @@ Class | Method | HTTP request | Description - [DescribeAppResponse](docs/DescribeAppResponse.md) - [DescribeAppVersionResponse](docs/DescribeAppVersionResponse.md) - [DescribeAuthenticationContextBody](docs/DescribeAuthenticationContextBody.md) + - [DescribeCatalogResponse](docs/DescribeCatalogResponse.md) - [DescribeDeviceLoginSessionResponse](docs/DescribeDeviceLoginSessionResponse.md) - [DescribeEmailPreferencesBody](docs/DescribeEmailPreferencesBody.md) - [DescribePlanResponse](docs/DescribePlanResponse.md) @@ -232,6 +242,7 @@ Class | Method | HTTP request | Description - [GenerateRunStatisticsResponse](docs/GenerateRunStatisticsResponse.md) - [GenerateRunnerCredentialsResponse](docs/GenerateRunnerCredentialsResponse.md) - [GetFeatureFlagResponseBody](docs/GetFeatureFlagResponseBody.md) + - [Guest](docs/Guest.md) - [InviteTeamMemberParams](docs/InviteTeamMemberParams.md) - [InviteTeamMemberResponse](docs/InviteTeamMemberResponse.md) - [LeaveTeamResponse](docs/LeaveTeamResponse.md) @@ -243,6 +254,7 @@ Class | Method | HTTP request | Description - [ListAuthenticatorsResponse](docs/ListAuthenticatorsResponse.md) - [ListCatalogsResponse](docs/ListCatalogsResponse.md) - [ListEnvironmentsResponse](docs/ListEnvironmentsResponse.md) + - [ListGuestsResponse](docs/ListGuestsResponse.md) - [ListMyTeamInvitationsResponse](docs/ListMyTeamInvitationsResponse.md) - [ListRunnersResponse](docs/ListRunnersResponse.md) - [ListRunsResponse](docs/ListRunsResponse.md) @@ -254,11 +266,14 @@ Class | Method | HTTP request | Description - [ListTeamsResponse](docs/ListTeamsResponse.md) - [ListWebhooksResponse](docs/ListWebhooksResponse.md) - [Organization](docs/Organization.md) + - [OrganizationUsage](docs/OrganizationUsage.md) - [Pagination](docs/Pagination.md) - [Parameter](docs/Parameter.md) - [Plan](docs/Plan.md) - [RefreshSessionParams](docs/RefreshSessionParams.md) - [RefreshSessionResponse](docs/RefreshSessionResponse.md) + - [RegenerateGuestLoginUrlParams](docs/RegenerateGuestLoginUrlParams.md) + - [RegenerateGuestLoginUrlResponse](docs/RegenerateGuestLoginUrlResponse.md) - [RemoveTeamMemberParams](docs/RemoveTeamMemberParams.md) - [RemoveTeamMemberResponse](docs/RemoveTeamMemberResponse.md) - [ResendTeamInvitationParams](docs/ResendTeamInvitationParams.md) @@ -267,6 +282,7 @@ Class | Method | HTTP request | Description - [RunAppInitiatorData](docs/RunAppInitiatorData.md) - [RunAppParams](docs/RunAppParams.md) - [RunAppResponse](docs/RunAppResponse.md) + - [RunAttempt](docs/RunAttempt.md) - [RunFailureAlert](docs/RunFailureAlert.md) - [RunGraphNode](docs/RunGraphNode.md) - [RunGraphRunId](docs/RunGraphRunId.md) @@ -275,6 +291,7 @@ Class | Method | HTTP request | Description - [RunLogLine](docs/RunLogLine.md) - [RunParameter](docs/RunParameter.md) - [RunResults](docs/RunResults.md) + - [RunRetryPolicy](docs/RunRetryPolicy.md) - [RunRunInitiatorDetails](docs/RunRunInitiatorDetails.md) - [RunStatistics](docs/RunStatistics.md) - [RunTimeseriesPoint](docs/RunTimeseriesPoint.md) @@ -326,6 +343,7 @@ Class | Method | HTTP request | Description - [UpdateUserResponse](docs/UpdateUserResponse.md) - [UpdateWebhookParams](docs/UpdateWebhookParams.md) - [UpdateWebhookResponse](docs/UpdateWebhookResponse.md) + - [UsageLimit](docs/UsageLimit.md) - [User](docs/User.md) - [VerifiedAuthenticator](docs/VerifiedAuthenticator.md) - [VerifyEmailParams](docs/VerifyEmailParams.md) diff --git a/crates/tower-api/src/apis/configuration.rs b/crates/tower-api/src/apis/configuration.rs index 0897d1fe..8a6ba675 100644 --- a/crates/tower-api/src/apis/configuration.rs +++ b/crates/tower-api/src/apis/configuration.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/apis/default_api.rs b/crates/tower-api/src/apis/default_api.rs index 3110a644..cca29216 100644 --- a/crates/tower-api/src/apis/default_api.rs +++ b/crates/tower-api/src/apis/default_api.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -85,6 +85,12 @@ pub struct CreateEnvironmentParams { pub create_environment_params: models::CreateEnvironmentParams, } +/// struct for passing parameters to the method [`create_guest`] +#[derive(Clone, Debug)] +pub struct CreateGuestParams { + pub create_guest_params: models::CreateGuestParams, +} + /// struct for passing parameters to the method [`create_password_reset`] #[derive(Clone, Debug)] pub struct CreatePasswordResetParams { @@ -168,6 +174,13 @@ pub struct DeleteCatalogParams { pub environment: Option, } +/// struct for passing parameters to the method [`delete_guest`] +#[derive(Clone, Debug)] +pub struct DeleteGuestParams { + /// The ID of the guest to delete. + pub guest_id: String, +} + /// struct for passing parameters to the method [`delete_schedule`] #[derive(Clone, Debug)] pub struct DeleteScheduleParams { @@ -254,6 +267,15 @@ pub struct DescribeAppVersionParams { pub num: String, } +/// struct for passing parameters to the method [`describe_catalog`] +#[derive(Clone, Debug)] +pub struct DescribeCatalogParams { + /// The name of the catalog. + pub name: String, + /// The environment of the catalog. + pub environment: Option, +} + /// struct for passing parameters to the method [`describe_device_login_session`] #[derive(Clone, Debug)] pub struct DescribeDeviceLoginSessionParams { @@ -452,6 +474,13 @@ pub struct ListEnvironmentsParams { pub page_size: Option, } +/// struct for passing parameters to the method [`list_guests`] +#[derive(Clone, Debug)] +pub struct ListGuestsParams { + /// Filter guests by app name. + pub app: Option, +} + /// struct for passing parameters to the method [`list_runners`] #[derive(Clone, Debug)] pub struct ListRunnersParams { @@ -542,6 +571,14 @@ pub struct RefreshSessionParams { pub refresh_session_params: models::RefreshSessionParams, } +/// struct for passing parameters to the method [`regenerate_guest_login_url`] +#[derive(Clone, Debug)] +pub struct RegenerateGuestLoginUrlParams { + /// The ID of the guest to regenerate the login URL for. + pub guest_id: String, + pub regenerate_guest_login_url_params: models::RegenerateGuestLoginUrlParams, +} + /// struct for passing parameters to the method [`remove_team_member`] #[derive(Clone, Debug)] pub struct RemoveTeamMemberParams { @@ -813,6 +850,14 @@ pub enum CreateEnvironmentSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`create_guest`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateGuestSuccess { + Status200(models::CreateGuestResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`create_password_reset`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -917,6 +962,14 @@ pub enum DeleteCatalogSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`delete_guest`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DeleteGuestSuccess { + Status204(models::DeleteGuestOutputBody), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`delete_schedule`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1005,6 +1058,14 @@ pub enum DescribeAuthenticationContextSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`describe_catalog`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DescribeCatalogSuccess { + Status200(models::DescribeCatalogResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`describe_device_login_session`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1021,6 +1082,14 @@ pub enum DescribeEmailPreferencesSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`describe_organization_usage`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DescribeOrganizationUsageSuccess { + Status200(models::OrganizationUsage), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`describe_plan`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1213,6 +1282,14 @@ pub enum ListEnvironmentsSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`list_guests`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ListGuestsSuccess { + Status200(models::ListGuestsResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`list_my_team_invitations`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1301,6 +1378,14 @@ pub enum RefreshSessionSuccess { UnknownValue(serde_json::Value), } +/// struct for typed successes of method [`regenerate_guest_login_url`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum RegenerateGuestLoginUrlSuccess { + Status200(models::RegenerateGuestLoginUrlResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed successes of method [`remove_team_member`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1597,6 +1682,14 @@ pub enum CreateEnvironmentError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`create_guest`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateGuestError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`create_password_reset`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1704,6 +1797,14 @@ pub enum DeleteCatalogError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`delete_guest`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DeleteGuestError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`delete_schedule`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1794,6 +1895,14 @@ pub enum DescribeAuthenticationContextError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`describe_catalog`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DescribeCatalogError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`describe_device_login_session`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -1810,6 +1919,14 @@ pub enum DescribeEmailPreferencesError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`describe_organization_usage`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DescribeOrganizationUsageError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`describe_plan`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -2004,6 +2121,14 @@ pub enum ListEnvironmentsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`list_guests`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ListGuestsError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`list_my_team_invitations`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -2092,6 +2217,14 @@ pub enum RefreshSessionError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`regenerate_guest_login_url`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum RegenerateGuestLoginUrlError { + DefaultResponse(models::ErrorModel), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`remove_team_member`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -2210,7 +2343,11 @@ pub enum UpdateMyTeamInvitationError { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum UpdateOrganizationError { - DefaultResponse(models::ErrorModel), + Status403(models::ErrorModel), + Status404(models::ErrorModel), + Status409(models::ErrorModel), + Status422(models::ErrorModel), + Status500(models::ErrorModel), UnknownValue(serde_json::Value), } @@ -3020,6 +3157,64 @@ pub async fn create_environment( } } +/// Creates a new guest with access to a specific externally accessible app and returns a login URL to share with them. +pub async fn create_guest( + configuration: &configuration::Configuration, + params: CreateGuestParams, +) -> Result, Error> { + let uri_str = format!("{}/guests", configuration.base_path); + let mut req_builder = configuration + .client + .request(reqwest::Method::POST, &uri_str); + + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + req_builder = req_builder.json(¶ms.create_guest_params); + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + /// Starts the password reset process for an account. If an email address exists for the account supplied, you will get a reset password email. pub async fn create_password_reset( configuration: &configuration::Configuration, @@ -3762,6 +3957,67 @@ pub async fn delete_catalog( } } +/// Deletes a guest and revokes their access. Any active sessions will be invalidated. +pub async fn delete_guest( + configuration: &configuration::Configuration, + params: DeleteGuestParams, +) -> Result, Error> { + let uri_str = format!( + "{}/guests/{guest_id}", + configuration.base_path, + guest_id = crate::apis::urlencode(params.guest_id) + ); + let mut req_builder = configuration + .client + .request(reqwest::Method::DELETE, &uri_str); + + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + /// Delete an existing schedule for an app. pub async fn delete_schedule( configuration: &configuration::Configuration, @@ -4439,6 +4695,68 @@ pub async fn describe_authentication_context( } } +/// Returns details for a specific catalog, including its property names and previews. +pub async fn describe_catalog( + configuration: &configuration::Configuration, + params: DescribeCatalogParams, +) -> Result, Error> { + let uri_str = format!( + "{}/catalogs/{name}", + configuration.base_path, + name = crate::apis::urlencode(params.name) + ); + let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str); + + if let Some(ref param_value) = params.environment { + req_builder = req_builder.query(&[("environment", ¶m_value.to_string())]); + } + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + /// Checks if a device login code has been claimed and returns the user session if so. pub async fn describe_device_login_session( configuration: &configuration::Configuration, @@ -4545,6 +4863,61 @@ pub async fn describe_email_preferences( } } +/// Describe usage statistics for the user's organization. +pub async fn describe_organization_usage( + configuration: &configuration::Configuration, +) -> Result, Error> +{ + let uri_str = format!("{}/usage", configuration.base_path); + let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str); + + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + /// Get the current plan for the account. pub async fn describe_plan( configuration: &configuration::Configuration, @@ -5449,7 +5822,7 @@ pub async fn invite_team_member( } } -/// Remove yourself from a team, if that's something you'd like to do for whatever reason. If you're the last member of a team, you cannot remove yourself. You should delete the team instead. +/// Remove yourself from a team. If you're the last member of a team, you cannot remove yourself. You should delete the team instead. pub async fn leave_team( configuration: &configuration::Configuration, params: LeaveTeamParams, @@ -6023,6 +6396,64 @@ pub async fn list_environments( } } +/// Lists all guests for the current account, optionally filtered by app. +pub async fn list_guests( + configuration: &configuration::Configuration, + params: ListGuestsParams, +) -> Result, Error> { + let uri_str = format!("{}/guests", configuration.base_path); + let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str); + + if let Some(ref param_value) = params.app { + req_builder = req_builder.query(&[("app", ¶m_value.to_string())]); + } + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + /// List your pending invitations for teams pub async fn list_my_team_invitations( configuration: &configuration::Configuration, @@ -6534,7 +6965,7 @@ pub async fn list_team_members( } } -/// List all the teams that the user is a member of. +/// List all the teams that you are a member of. pub async fn list_teams( configuration: &configuration::Configuration, params: ListTeamsParams, @@ -6713,6 +7144,68 @@ pub async fn refresh_session( } } +/// Creates a new login URL for an existing guest. Use this if the previous URL expired or was compromised. +pub async fn regenerate_guest_login_url( + configuration: &configuration::Configuration, + params: RegenerateGuestLoginUrlParams, +) -> Result, Error> { + let uri_str = format!( + "{}/guests/{guest_id}/login-url", + configuration.base_path, + guest_id = crate::apis::urlencode(params.guest_id) + ); + let mut req_builder = configuration + .client + .request(reqwest::Method::POST, &uri_str); + + if let Some(ref user_agent) = configuration.user_agent { + req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone()); + } + if let Some(ref token) = configuration.bearer_access_token { + req_builder = req_builder.bearer_auth(token.to_owned()); + }; + if let Some(ref apikey) = configuration.api_key { + let key = apikey.key.clone(); + let value = match apikey.prefix { + Some(ref prefix) => format!("{} {}", prefix, key), + None => key, + }; + req_builder = req_builder.header("X-API-Key", value); + }; + req_builder = req_builder.json(¶ms.regenerate_guest_login_url_params); + + let req = req_builder.build()?; + let resp = configuration.client.execute(req).await?; + + let status = resp.status(); + + let tower_trace_id = resp + .headers() + .get("x-tower-trace-id") + .and_then(|v| v.to_str().ok()) + .map_or(String::from(DEFAULT_TOWER_TRACE_ID), String::from); + + if !status.is_client_error() && !status.is_server_error() { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Ok(ResponseContent { + tower_trace_id, + status, + content, + entity, + }) + } else { + let content = resp.text().await?; + let entity: Option = serde_json::from_str(&content).ok(); + Err(Error::ResponseError(ResponseContent { + tower_trace_id, + status, + content, + entity, + })) + } +} + pub async fn remove_team_member( configuration: &configuration::Configuration, params: RemoveTeamMemberParams, diff --git a/crates/tower-api/src/apis/feature_flags_api.rs b/crates/tower-api/src/apis/feature_flags_api.rs index 19e274a6..3aff42f5 100644 --- a/crates/tower-api/src/apis/feature_flags_api.rs +++ b/crates/tower-api/src/apis/feature_flags_api.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/account.rs b/crates/tower-api/src/models/account.rs index cf559f4a..3a845a34 100644 --- a/crates/tower-api/src/models/account.rs +++ b/crates/tower-api/src/models/account.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -14,6 +14,9 @@ use serde_with::{serde_as, DefaultOnNull}; #[serde_as] #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct Account { + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "execution_region")] + pub execution_region: String, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "is_self_hosted_only")] pub is_self_hosted_only: bool, @@ -26,8 +29,9 @@ pub struct Account { } impl Account { - pub fn new(is_self_hosted_only: bool, name: String) -> Account { + pub fn new(execution_region: String, is_self_hosted_only: bool, name: String) -> Account { Account { + execution_region, is_self_hosted_only, name, slug: None, diff --git a/crates/tower-api/src/models/acknowledge_alert_response.rs b/crates/tower-api/src/models/acknowledge_alert_response.rs index c09af3d1..782d260b 100644 --- a/crates/tower-api/src/models/acknowledge_alert_response.rs +++ b/crates/tower-api/src/models/acknowledge_alert_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/acknowledge_all_alerts_response.rs b/crates/tower-api/src/models/acknowledge_all_alerts_response.rs index 03ad0d97..8a592c5a 100644 --- a/crates/tower-api/src/models/acknowledge_all_alerts_response.rs +++ b/crates/tower-api/src/models/acknowledge_all_alerts_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/alert.rs b/crates/tower-api/src/models/alert.rs index c0f324df..87f09bec 100644 --- a/crates/tower-api/src/models/alert.rs +++ b/crates/tower-api/src/models/alert.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/api_key.rs b/crates/tower-api/src/models/api_key.rs index 296bb0b0..88e955b0 100644 --- a/crates/tower-api/src/models/api_key.rs +++ b/crates/tower-api/src/models/api_key.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -17,6 +17,8 @@ pub struct ApiKey { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "created_at")] pub created_at: String, + #[serde(rename = "expires_at", skip_serializing_if = "Option::is_none")] + pub expires_at: Option, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "identifier")] pub identifier: String, @@ -25,6 +27,8 @@ pub struct ApiKey { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "name")] pub name: String, + #[serde(rename = "scopes", skip_serializing_if = "Option::is_none")] + pub scopes: Option, } impl ApiKey { @@ -36,9 +40,11 @@ impl ApiKey { ) -> ApiKey { ApiKey { created_at, + expires_at: None, identifier, last_used_at, name, + scopes: None, } } } diff --git a/crates/tower-api/src/models/app.rs b/crates/tower-api/src/models/app.rs index ce3f61cb..937837f3 100644 --- a/crates/tower-api/src/models/app.rs +++ b/crates/tower-api/src/models/app.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -43,6 +43,9 @@ pub struct App { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "pending_timeout")] pub pending_timeout: i64, + /// The retry policy for failed runs of this app. + #[serde(rename = "retry_policy", skip_serializing_if = "Option::is_none")] + pub retry_policy: Option, /// The stats of all the runs of this app. #[serde(rename = "run_results", skip_serializing_if = "Option::is_none")] pub run_results: Option, @@ -94,6 +97,7 @@ impl App { next_run_at, owner, pending_timeout, + retry_policy: None, run_results: None, running_timeout, schedule, diff --git a/crates/tower-api/src/models/app_statistics.rs b/crates/tower-api/src/models/app_statistics.rs index bdee61e7..5eca4ab8 100644 --- a/crates/tower-api/src/models/app_statistics.rs +++ b/crates/tower-api/src/models/app_statistics.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/app_summary.rs b/crates/tower-api/src/models/app_summary.rs index e6a7ba70..9dc5c5f8 100644 --- a/crates/tower-api/src/models/app_summary.rs +++ b/crates/tower-api/src/models/app_summary.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/app_version.rs b/crates/tower-api/src/models/app_version.rs index d68f0720..09df0920 100644 --- a/crates/tower-api/src/models/app_version.rs +++ b/crates/tower-api/src/models/app_version.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/authentication_context.rs b/crates/tower-api/src/models/authentication_context.rs index 3485683e..871d5073 100644 --- a/crates/tower-api/src/models/authentication_context.rs +++ b/crates/tower-api/src/models/authentication_context.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/batch_schedule_params.rs b/crates/tower-api/src/models/batch_schedule_params.rs index add24560..30733ad9 100644 --- a/crates/tower-api/src/models/batch_schedule_params.rs +++ b/crates/tower-api/src/models/batch_schedule_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/batch_schedule_response.rs b/crates/tower-api/src/models/batch_schedule_response.rs index 68b7734c..547101d8 100644 --- a/crates/tower-api/src/models/batch_schedule_response.rs +++ b/crates/tower-api/src/models/batch_schedule_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/cancel_run_response.rs b/crates/tower-api/src/models/cancel_run_response.rs index 65de24c0..837e0020 100644 --- a/crates/tower-api/src/models/cancel_run_response.rs +++ b/crates/tower-api/src/models/cancel_run_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/catalog.rs b/crates/tower-api/src/models/catalog.rs index e19b6326..9da31e96 100644 --- a/crates/tower-api/src/models/catalog.rs +++ b/crates/tower-api/src/models/catalog.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/catalog_property.rs b/crates/tower-api/src/models/catalog_property.rs index 14a78c95..3a931689 100644 --- a/crates/tower-api/src/models/catalog_property.rs +++ b/crates/tower-api/src/models/catalog_property.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/claim_device_login_ticket_params.rs b/crates/tower-api/src/models/claim_device_login_ticket_params.rs index 008b80be..8507bf4b 100644 --- a/crates/tower-api/src/models/claim_device_login_ticket_params.rs +++ b/crates/tower-api/src/models/claim_device_login_ticket_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/claim_device_login_ticket_response.rs b/crates/tower-api/src/models/claim_device_login_ticket_response.rs index 9bf6ecd1..e8aacd4b 100644 --- a/crates/tower-api/src/models/claim_device_login_ticket_response.rs +++ b/crates/tower-api/src/models/claim_device_login_ticket_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_account_params.rs b/crates/tower-api/src/models/create_account_params.rs index d41b4011..d9989c40 100644 --- a/crates/tower-api/src/models/create_account_params.rs +++ b/crates/tower-api/src/models/create_account_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_account_params_flags_struct.rs b/crates/tower-api/src/models/create_account_params_flags_struct.rs index 5e1a98ec..d99ffe12 100644 --- a/crates/tower-api/src/models/create_account_params_flags_struct.rs +++ b/crates/tower-api/src/models/create_account_params_flags_struct.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_account_response.rs b/crates/tower-api/src/models/create_account_response.rs index b287529d..ff72f515 100644 --- a/crates/tower-api/src/models/create_account_response.rs +++ b/crates/tower-api/src/models/create_account_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_api_key_params.rs b/crates/tower-api/src/models/create_api_key_params.rs index 0f822c77..74396793 100644 --- a/crates/tower-api/src/models/create_api_key_params.rs +++ b/crates/tower-api/src/models/create_api_key_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -17,13 +17,43 @@ pub struct CreateApiKeyParams { /// A URL to the JSON Schema for this object. #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] pub schema: Option, + /// When this API key expires. + #[serde( + rename = "expires_at", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub expires_at: Option>, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "name")] pub name: String, + /// Space separated scopes that this API key is valid for. + #[serde( + rename = "scopes", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub scopes: Option>, + /// The team this API key is associated with. This field is optional. You must be a member of the team that you're creating the API key for, and if you're using an API key to create a new API key, the API key you use to authenticate this request must be a personal API key. + #[serde( + rename = "team", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub team: Option>, } impl CreateApiKeyParams { pub fn new(name: String) -> CreateApiKeyParams { - CreateApiKeyParams { schema: None, name } + CreateApiKeyParams { + schema: None, + expires_at: None, + name, + scopes: None, + team: None, + } } } diff --git a/crates/tower-api/src/models/create_api_key_response.rs b/crates/tower-api/src/models/create_api_key_response.rs index b08d1e0c..b8f734aa 100644 --- a/crates/tower-api/src/models/create_api_key_response.rs +++ b/crates/tower-api/src/models/create_api_key_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_app_params.rs b/crates/tower-api/src/models/create_app_params.rs index d4b9860f..3f833799 100644 --- a/crates/tower-api/src/models/create_app_params.rs +++ b/crates/tower-api/src/models/create_app_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_app_response.rs b/crates/tower-api/src/models/create_app_response.rs index 8c83a5c3..b58e8798 100644 --- a/crates/tower-api/src/models/create_app_response.rs +++ b/crates/tower-api/src/models/create_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_authenticator_params.rs b/crates/tower-api/src/models/create_authenticator_params.rs index c68f8f86..22baa6a2 100644 --- a/crates/tower-api/src/models/create_authenticator_params.rs +++ b/crates/tower-api/src/models/create_authenticator_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_authenticator_response.rs b/crates/tower-api/src/models/create_authenticator_response.rs index 28d955a7..f81e33a2 100644 --- a/crates/tower-api/src/models/create_authenticator_response.rs +++ b/crates/tower-api/src/models/create_authenticator_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_catalog_params.rs b/crates/tower-api/src/models/create_catalog_params.rs index ebaf9bd8..9aa008de 100644 --- a/crates/tower-api/src/models/create_catalog_params.rs +++ b/crates/tower-api/src/models/create_catalog_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_catalog_response.rs b/crates/tower-api/src/models/create_catalog_response.rs index 27533731..9398f67d 100644 --- a/crates/tower-api/src/models/create_catalog_response.rs +++ b/crates/tower-api/src/models/create_catalog_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_device_login_ticket_response.rs b/crates/tower-api/src/models/create_device_login_ticket_response.rs index 42b7a73b..b2fda489 100644 --- a/crates/tower-api/src/models/create_device_login_ticket_response.rs +++ b/crates/tower-api/src/models/create_device_login_ticket_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_environment_params.rs b/crates/tower-api/src/models/create_environment_params.rs index c64a7513..72cc1bd3 100644 --- a/crates/tower-api/src/models/create_environment_params.rs +++ b/crates/tower-api/src/models/create_environment_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_environment_response.rs b/crates/tower-api/src/models/create_environment_response.rs index 1701d7f0..06bf2b30 100644 --- a/crates/tower-api/src/models/create_environment_response.rs +++ b/crates/tower-api/src/models/create_environment_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_guest_params.rs b/crates/tower-api/src/models/create_guest_params.rs new file mode 100644 index 00000000..9e751d22 --- /dev/null +++ b/crates/tower-api/src/models/create_guest_params.rs @@ -0,0 +1,45 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct CreateGuestParams { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// The name of the externally accessible app this guest can access. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "app")] + pub app: String, + /// The number of seconds the guest session should last. Defaults to 72 hours. + #[serde(rename = "expires_in", skip_serializing_if = "Option::is_none")] + pub expires_in: Option, + /// Optional display name for the guest. + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + /// Where to redirect the guest after they log in. Defaults to the app's subdomain. + #[serde(rename = "redirect_url", skip_serializing_if = "Option::is_none")] + pub redirect_url: Option, +} + +impl CreateGuestParams { + pub fn new(app: String) -> CreateGuestParams { + CreateGuestParams { + schema: None, + app, + expires_in: None, + name: None, + redirect_url: None, + } + } +} diff --git a/crates/tower-api/src/models/create_guest_response.rs b/crates/tower-api/src/models/create_guest_response.rs new file mode 100644 index 00000000..303cdbb5 --- /dev/null +++ b/crates/tower-api/src/models/create_guest_response.rs @@ -0,0 +1,47 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct CreateGuestResponse { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// The created guest. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "guest")] + pub guest: models::Guest, + /// The URL to share with the guest for logging in. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "login_url")] + pub login_url: String, + /// When the login URL expires. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "login_url_expires_at")] + pub login_url_expires_at: String, +} + +impl CreateGuestResponse { + pub fn new( + guest: models::Guest, + login_url: String, + login_url_expires_at: String, + ) -> CreateGuestResponse { + CreateGuestResponse { + schema: None, + guest, + login_url, + login_url_expires_at, + } + } +} diff --git a/crates/tower-api/src/models/create_password_reset_params.rs b/crates/tower-api/src/models/create_password_reset_params.rs index 20b49a65..bd459d52 100644 --- a/crates/tower-api/src/models/create_password_reset_params.rs +++ b/crates/tower-api/src/models/create_password_reset_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_password_reset_response.rs b/crates/tower-api/src/models/create_password_reset_response.rs index 5511300b..4dc6aaba 100644 --- a/crates/tower-api/src/models/create_password_reset_response.rs +++ b/crates/tower-api/src/models/create_password_reset_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_sandbox_secrets_params.rs b/crates/tower-api/src/models/create_sandbox_secrets_params.rs index 155b02a9..8b887931 100644 --- a/crates/tower-api/src/models/create_sandbox_secrets_params.rs +++ b/crates/tower-api/src/models/create_sandbox_secrets_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_sandbox_secrets_response.rs b/crates/tower-api/src/models/create_sandbox_secrets_response.rs index bd4b5d49..928f2a73 100644 --- a/crates/tower-api/src/models/create_sandbox_secrets_response.rs +++ b/crates/tower-api/src/models/create_sandbox_secrets_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_schedule_params.rs b/crates/tower-api/src/models/create_schedule_params.rs index 0722dafd..16521859 100644 --- a/crates/tower-api/src/models/create_schedule_params.rs +++ b/crates/tower-api/src/models/create_schedule_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -63,6 +63,14 @@ pub struct CreateScheduleParams { skip_serializing_if = "Option::is_none" )] pub status: Option>, + /// The IANA timezone identifier that the cron expression should be evaluated in (e.g., 'America/New_York', 'Europe/London'). Defaults to 'UTC'. + #[serde( + rename = "timezone", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub timezone: Option>, } impl CreateScheduleParams { @@ -77,6 +85,7 @@ impl CreateScheduleParams { overlap_policy: None, parameters: None, status: None, + timezone: None, } } } diff --git a/crates/tower-api/src/models/create_schedule_response.rs b/crates/tower-api/src/models/create_schedule_response.rs index 2250bb90..193a15ad 100644 --- a/crates/tower-api/src/models/create_schedule_response.rs +++ b/crates/tower-api/src/models/create_schedule_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_secret_params.rs b/crates/tower-api/src/models/create_secret_params.rs index f24537c9..ca80c9d0 100644 --- a/crates/tower-api/src/models/create_secret_params.rs +++ b/crates/tower-api/src/models/create_secret_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_secret_response.rs b/crates/tower-api/src/models/create_secret_response.rs index 772e0eb3..2883f783 100644 --- a/crates/tower-api/src/models/create_secret_response.rs +++ b/crates/tower-api/src/models/create_secret_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_session_params.rs b/crates/tower-api/src/models/create_session_params.rs index 60eed470..e14ac427 100644 --- a/crates/tower-api/src/models/create_session_params.rs +++ b/crates/tower-api/src/models/create_session_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_session_response.rs b/crates/tower-api/src/models/create_session_response.rs index d415e053..0d47049c 100644 --- a/crates/tower-api/src/models/create_session_response.rs +++ b/crates/tower-api/src/models/create_session_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_team_params.rs b/crates/tower-api/src/models/create_team_params.rs index f09628d3..f7e6dcb3 100644 --- a/crates/tower-api/src/models/create_team_params.rs +++ b/crates/tower-api/src/models/create_team_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_team_response.rs b/crates/tower-api/src/models/create_team_response.rs index be169e58..93ccb30f 100644 --- a/crates/tower-api/src/models/create_team_response.rs +++ b/crates/tower-api/src/models/create_team_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_webhook_params.rs b/crates/tower-api/src/models/create_webhook_params.rs index 3f2ffce5..c26331f2 100644 --- a/crates/tower-api/src/models/create_webhook_params.rs +++ b/crates/tower-api/src/models/create_webhook_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/create_webhook_response.rs b/crates/tower-api/src/models/create_webhook_response.rs index dffd45b3..539ffe82 100644 --- a/crates/tower-api/src/models/create_webhook_response.rs +++ b/crates/tower-api/src/models/create_webhook_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_api_key_params.rs b/crates/tower-api/src/models/delete_api_key_params.rs index 86fc1f8e..5957f029 100644 --- a/crates/tower-api/src/models/delete_api_key_params.rs +++ b/crates/tower-api/src/models/delete_api_key_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_api_key_response.rs b/crates/tower-api/src/models/delete_api_key_response.rs index 4832a796..c4cac0f3 100644 --- a/crates/tower-api/src/models/delete_api_key_response.rs +++ b/crates/tower-api/src/models/delete_api_key_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_app_response.rs b/crates/tower-api/src/models/delete_app_response.rs index 9b464f0e..90ba591c 100644 --- a/crates/tower-api/src/models/delete_app_response.rs +++ b/crates/tower-api/src/models/delete_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_authenticator_params.rs b/crates/tower-api/src/models/delete_authenticator_params.rs index 50025867..323a2d7f 100644 --- a/crates/tower-api/src/models/delete_authenticator_params.rs +++ b/crates/tower-api/src/models/delete_authenticator_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_authenticator_response.rs b/crates/tower-api/src/models/delete_authenticator_response.rs index 38a0c591..65c214ac 100644 --- a/crates/tower-api/src/models/delete_authenticator_response.rs +++ b/crates/tower-api/src/models/delete_authenticator_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_catalog_response.rs b/crates/tower-api/src/models/delete_catalog_response.rs index f14327e1..f8c869e0 100644 --- a/crates/tower-api/src/models/delete_catalog_response.rs +++ b/crates/tower-api/src/models/delete_catalog_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_guest_output_body.rs b/crates/tower-api/src/models/delete_guest_output_body.rs new file mode 100644 index 00000000..fdbcc7d6 --- /dev/null +++ b/crates/tower-api/src/models/delete_guest_output_body.rs @@ -0,0 +1,26 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct DeleteGuestOutputBody { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, +} + +impl DeleteGuestOutputBody { + pub fn new() -> DeleteGuestOutputBody { + DeleteGuestOutputBody { schema: None } + } +} diff --git a/crates/tower-api/src/models/delete_schedule_params.rs b/crates/tower-api/src/models/delete_schedule_params.rs index 730d4c1d..4da4d4e9 100644 --- a/crates/tower-api/src/models/delete_schedule_params.rs +++ b/crates/tower-api/src/models/delete_schedule_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_schedule_response.rs b/crates/tower-api/src/models/delete_schedule_response.rs index 9a193cbf..08f88cc5 100644 --- a/crates/tower-api/src/models/delete_schedule_response.rs +++ b/crates/tower-api/src/models/delete_schedule_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_secret_response.rs b/crates/tower-api/src/models/delete_secret_response.rs index e89d0184..c462452f 100644 --- a/crates/tower-api/src/models/delete_secret_response.rs +++ b/crates/tower-api/src/models/delete_secret_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_session_params.rs b/crates/tower-api/src/models/delete_session_params.rs index d3d5dcd7..08078b86 100644 --- a/crates/tower-api/src/models/delete_session_params.rs +++ b/crates/tower-api/src/models/delete_session_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_session_response.rs b/crates/tower-api/src/models/delete_session_response.rs index 821fd307..bccb97e8 100644 --- a/crates/tower-api/src/models/delete_session_response.rs +++ b/crates/tower-api/src/models/delete_session_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_team_invitation_params.rs b/crates/tower-api/src/models/delete_team_invitation_params.rs index 2bbd18e7..be874ec2 100644 --- a/crates/tower-api/src/models/delete_team_invitation_params.rs +++ b/crates/tower-api/src/models/delete_team_invitation_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_team_invitation_response.rs b/crates/tower-api/src/models/delete_team_invitation_response.rs index 375a85c9..6601856a 100644 --- a/crates/tower-api/src/models/delete_team_invitation_response.rs +++ b/crates/tower-api/src/models/delete_team_invitation_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_team_params.rs b/crates/tower-api/src/models/delete_team_params.rs index 18aa210e..464284dc 100644 --- a/crates/tower-api/src/models/delete_team_params.rs +++ b/crates/tower-api/src/models/delete_team_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_team_response.rs b/crates/tower-api/src/models/delete_team_response.rs index 8af36c48..ff7b6eb0 100644 --- a/crates/tower-api/src/models/delete_team_response.rs +++ b/crates/tower-api/src/models/delete_team_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/delete_webhook_response.rs b/crates/tower-api/src/models/delete_webhook_response.rs index 576a8143..e72f91a1 100644 --- a/crates/tower-api/src/models/delete_webhook_response.rs +++ b/crates/tower-api/src/models/delete_webhook_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/deploy_app_request.rs b/crates/tower-api/src/models/deploy_app_request.rs index c78ff26a..365e7a4a 100644 --- a/crates/tower-api/src/models/deploy_app_request.rs +++ b/crates/tower-api/src/models/deploy_app_request.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/deploy_app_response.rs b/crates/tower-api/src/models/deploy_app_response.rs index d3f32fbd..08c7a64e 100644 --- a/crates/tower-api/src/models/deploy_app_response.rs +++ b/crates/tower-api/src/models/deploy_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_account_body.rs b/crates/tower-api/src/models/describe_account_body.rs index f0386a19..9a140070 100644 --- a/crates/tower-api/src/models/describe_account_body.rs +++ b/crates/tower-api/src/models/describe_account_body.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_app_response.rs b/crates/tower-api/src/models/describe_app_response.rs index b6bced63..7595f4a3 100644 --- a/crates/tower-api/src/models/describe_app_response.rs +++ b/crates/tower-api/src/models/describe_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_app_version_response.rs b/crates/tower-api/src/models/describe_app_version_response.rs index e605dae3..4c3864b8 100644 --- a/crates/tower-api/src/models/describe_app_version_response.rs +++ b/crates/tower-api/src/models/describe_app_version_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_authentication_context_body.rs b/crates/tower-api/src/models/describe_authentication_context_body.rs index 53225a17..5f3c871a 100644 --- a/crates/tower-api/src/models/describe_authentication_context_body.rs +++ b/crates/tower-api/src/models/describe_authentication_context_body.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_catalog_response.rs b/crates/tower-api/src/models/describe_catalog_response.rs new file mode 100644 index 00000000..67e169a1 --- /dev/null +++ b/crates/tower-api/src/models/describe_catalog_response.rs @@ -0,0 +1,32 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct DescribeCatalogResponse { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "catalog")] + pub catalog: models::Catalog, +} + +impl DescribeCatalogResponse { + pub fn new(catalog: models::Catalog) -> DescribeCatalogResponse { + DescribeCatalogResponse { + schema: None, + catalog, + } + } +} diff --git a/crates/tower-api/src/models/describe_device_login_session_response.rs b/crates/tower-api/src/models/describe_device_login_session_response.rs index a5e83084..47baa036 100644 --- a/crates/tower-api/src/models/describe_device_login_session_response.rs +++ b/crates/tower-api/src/models/describe_device_login_session_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_email_preferences_body.rs b/crates/tower-api/src/models/describe_email_preferences_body.rs index af7061a4..88eb698c 100644 --- a/crates/tower-api/src/models/describe_email_preferences_body.rs +++ b/crates/tower-api/src/models/describe_email_preferences_body.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_plan_response.rs b/crates/tower-api/src/models/describe_plan_response.rs index 518e2e06..5a627dec 100644 --- a/crates/tower-api/src/models/describe_plan_response.rs +++ b/crates/tower-api/src/models/describe_plan_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_run_graph_response.rs b/crates/tower-api/src/models/describe_run_graph_response.rs index a1598872..838fc817 100644 --- a/crates/tower-api/src/models/describe_run_graph_response.rs +++ b/crates/tower-api/src/models/describe_run_graph_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_run_links.rs b/crates/tower-api/src/models/describe_run_links.rs index 80812642..07f769b0 100644 --- a/crates/tower-api/src/models/describe_run_links.rs +++ b/crates/tower-api/src/models/describe_run_links.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -17,9 +17,15 @@ pub struct DescribeRunLinks { /// The URL of the next run, if any. #[serde(rename = "next", deserialize_with = "Option::deserialize")] pub next: Option, + /// The number of the next run, if any. + #[serde(rename = "next_number", deserialize_with = "Option::deserialize")] + pub next_number: Option, /// The URL of the previous run, if any. #[serde(rename = "prev", deserialize_with = "Option::deserialize")] pub prev: Option, + /// The number of the previous run, if any. + #[serde(rename = "prev_number", deserialize_with = "Option::deserialize")] + pub prev_number: Option, /// The URL of this run. #[serde_as(as = "DefaultOnNull")] #[serde(rename = "self")] @@ -27,10 +33,18 @@ pub struct DescribeRunLinks { } impl DescribeRunLinks { - pub fn new(next: Option, prev: Option, param_self: String) -> DescribeRunLinks { + pub fn new( + next: Option, + next_number: Option, + prev: Option, + prev_number: Option, + param_self: String, + ) -> DescribeRunLinks { DescribeRunLinks { next, + next_number, prev, + prev_number, param_self, } } diff --git a/crates/tower-api/src/models/describe_run_logs_response.rs b/crates/tower-api/src/models/describe_run_logs_response.rs index 8f4e91f6..931414b4 100644 --- a/crates/tower-api/src/models/describe_run_logs_response.rs +++ b/crates/tower-api/src/models/describe_run_logs_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_run_response.rs b/crates/tower-api/src/models/describe_run_response.rs index 40f8326b..48567a3a 100644 --- a/crates/tower-api/src/models/describe_run_response.rs +++ b/crates/tower-api/src/models/describe_run_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_secrets_key_response.rs b/crates/tower-api/src/models/describe_secrets_key_response.rs index 03c0fb8f..fe6fc84d 100644 --- a/crates/tower-api/src/models/describe_secrets_key_response.rs +++ b/crates/tower-api/src/models/describe_secrets_key_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_session_response.rs b/crates/tower-api/src/models/describe_session_response.rs index 5242f053..c71ee96f 100644 --- a/crates/tower-api/src/models/describe_session_response.rs +++ b/crates/tower-api/src/models/describe_session_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_team_response.rs b/crates/tower-api/src/models/describe_team_response.rs index adbd317c..4cb061e4 100644 --- a/crates/tower-api/src/models/describe_team_response.rs +++ b/crates/tower-api/src/models/describe_team_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/describe_webhook_response.rs b/crates/tower-api/src/models/describe_webhook_response.rs index beebade2..81b721f5 100644 --- a/crates/tower-api/src/models/describe_webhook_response.rs +++ b/crates/tower-api/src/models/describe_webhook_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/email_subscriptions.rs b/crates/tower-api/src/models/email_subscriptions.rs index 0e170de0..714dccd8 100644 --- a/crates/tower-api/src/models/email_subscriptions.rs +++ b/crates/tower-api/src/models/email_subscriptions.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/encrypted_catalog_property.rs b/crates/tower-api/src/models/encrypted_catalog_property.rs index b46c7367..9b8dbb02 100644 --- a/crates/tower-api/src/models/encrypted_catalog_property.rs +++ b/crates/tower-api/src/models/encrypted_catalog_property.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/environment.rs b/crates/tower-api/src/models/environment.rs index b480c1f1..d133f4f4 100644 --- a/crates/tower-api/src/models/environment.rs +++ b/crates/tower-api/src/models/environment.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/error_detail.rs b/crates/tower-api/src/models/error_detail.rs index 20436fee..b0e32788 100644 --- a/crates/tower-api/src/models/error_detail.rs +++ b/crates/tower-api/src/models/error_detail.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/error_model.rs b/crates/tower-api/src/models/error_model.rs index 09160ca7..2bcee07d 100644 --- a/crates/tower-api/src/models/error_model.rs +++ b/crates/tower-api/src/models/error_model.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/event_alert.rs b/crates/tower-api/src/models/event_alert.rs index 754229b8..1f8f0f37 100644 --- a/crates/tower-api/src/models/event_alert.rs +++ b/crates/tower-api/src/models/event_alert.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/event_error.rs b/crates/tower-api/src/models/event_error.rs index 90dc0c69..649662f0 100644 --- a/crates/tower-api/src/models/event_error.rs +++ b/crates/tower-api/src/models/event_error.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/event_log.rs b/crates/tower-api/src/models/event_log.rs index 2f1d278b..7151ffe4 100644 --- a/crates/tower-api/src/models/event_log.rs +++ b/crates/tower-api/src/models/event_log.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/event_shouldertap.rs b/crates/tower-api/src/models/event_shouldertap.rs index 2c170723..b60742e5 100644 --- a/crates/tower-api/src/models/event_shouldertap.rs +++ b/crates/tower-api/src/models/event_shouldertap.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/event_warning.rs b/crates/tower-api/src/models/event_warning.rs index 208ea897..c282dd58 100644 --- a/crates/tower-api/src/models/event_warning.rs +++ b/crates/tower-api/src/models/event_warning.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/export_catalogs_params.rs b/crates/tower-api/src/models/export_catalogs_params.rs index 08809fd4..1796b809 100644 --- a/crates/tower-api/src/models/export_catalogs_params.rs +++ b/crates/tower-api/src/models/export_catalogs_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/export_catalogs_response.rs b/crates/tower-api/src/models/export_catalogs_response.rs index 7d492567..80aff717 100644 --- a/crates/tower-api/src/models/export_catalogs_response.rs +++ b/crates/tower-api/src/models/export_catalogs_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/export_secrets_params.rs b/crates/tower-api/src/models/export_secrets_params.rs index 076e82de..debf3fdb 100644 --- a/crates/tower-api/src/models/export_secrets_params.rs +++ b/crates/tower-api/src/models/export_secrets_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/export_secrets_response.rs b/crates/tower-api/src/models/export_secrets_response.rs index a8597f9b..46639017 100644 --- a/crates/tower-api/src/models/export_secrets_response.rs +++ b/crates/tower-api/src/models/export_secrets_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/exported_catalog.rs b/crates/tower-api/src/models/exported_catalog.rs index 70973c42..94c60aa7 100644 --- a/crates/tower-api/src/models/exported_catalog.rs +++ b/crates/tower-api/src/models/exported_catalog.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/exported_catalog_property.rs b/crates/tower-api/src/models/exported_catalog_property.rs index 2404cdce..85520e3e 100644 --- a/crates/tower-api/src/models/exported_catalog_property.rs +++ b/crates/tower-api/src/models/exported_catalog_property.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/exported_secret.rs b/crates/tower-api/src/models/exported_secret.rs index aaef7714..2a1b6a6c 100644 --- a/crates/tower-api/src/models/exported_secret.rs +++ b/crates/tower-api/src/models/exported_secret.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/feature.rs b/crates/tower-api/src/models/feature.rs index ff0abdd8..96ec8033 100644 --- a/crates/tower-api/src/models/feature.rs +++ b/crates/tower-api/src/models/feature.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/featurebase_identity.rs b/crates/tower-api/src/models/featurebase_identity.rs index 762f6f9c..a5358dca 100644 --- a/crates/tower-api/src/models/featurebase_identity.rs +++ b/crates/tower-api/src/models/featurebase_identity.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/generate_app_statistics_response.rs b/crates/tower-api/src/models/generate_app_statistics_response.rs index 9849ae28..2ff6f071 100644 --- a/crates/tower-api/src/models/generate_app_statistics_response.rs +++ b/crates/tower-api/src/models/generate_app_statistics_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/generate_authenticator_response.rs b/crates/tower-api/src/models/generate_authenticator_response.rs index 9d1f2b0a..636f0794 100644 --- a/crates/tower-api/src/models/generate_authenticator_response.rs +++ b/crates/tower-api/src/models/generate_authenticator_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/generate_run_statistics_response.rs b/crates/tower-api/src/models/generate_run_statistics_response.rs index a17343b7..6b1de3bd 100644 --- a/crates/tower-api/src/models/generate_run_statistics_response.rs +++ b/crates/tower-api/src/models/generate_run_statistics_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/generate_runner_credentials_response.rs b/crates/tower-api/src/models/generate_runner_credentials_response.rs index c1e90c4e..93265dc9 100644 --- a/crates/tower-api/src/models/generate_runner_credentials_response.rs +++ b/crates/tower-api/src/models/generate_runner_credentials_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/get_feature_flag_response_body.rs b/crates/tower-api/src/models/get_feature_flag_response_body.rs index cee7b7b6..e73142c0 100644 --- a/crates/tower-api/src/models/get_feature_flag_response_body.rs +++ b/crates/tower-api/src/models/get_feature_flag_response_body.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/guest.rs b/crates/tower-api/src/models/guest.rs new file mode 100644 index 00000000..1f3996a1 --- /dev/null +++ b/crates/tower-api/src/models/guest.rs @@ -0,0 +1,43 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct Guest { + /// The name of the app this guest can access. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "app")] + pub app: String, + /// When the guest was created. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "created_at")] + pub created_at: String, + /// The unique identifier for the guest. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "id")] + pub id: String, + /// Optional display name for the guest. + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, +} + +impl Guest { + pub fn new(app: String, created_at: String, id: String) -> Guest { + Guest { + app, + created_at, + id, + name: None, + } + } +} diff --git a/crates/tower-api/src/models/invite_team_member_params.rs b/crates/tower-api/src/models/invite_team_member_params.rs index 3280c32e..608a819f 100644 --- a/crates/tower-api/src/models/invite_team_member_params.rs +++ b/crates/tower-api/src/models/invite_team_member_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -24,14 +24,49 @@ pub struct InviteTeamMemberParams { /// Optional message to include in the invite email #[serde(rename = "message", skip_serializing_if = "Option::is_none")] pub message: Option, + /// The role to assign to the invitations + #[serde(rename = "role", deserialize_with = "Option::deserialize")] + pub role: Option, } impl InviteTeamMemberParams { - pub fn new(emails: String) -> InviteTeamMemberParams { + pub fn new(emails: String, role: Option) -> InviteTeamMemberParams { InviteTeamMemberParams { schema: None, emails, message: None, + role, + } + } +} +/// The role to assign to the invitations +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +pub enum Role { + #[serde(rename = "admin")] + Admin, + #[serde(rename = "developer")] + Developer, +} + +impl Default for Role { + fn default() -> Role { + Self::Admin + } +} + +impl<'de> Deserialize<'de> for Role { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + match s.to_lowercase().as_str() { + "admin" => Ok(Self::Admin), + "developer" => Ok(Self::Developer), + _ => Err(serde::de::Error::unknown_variant( + &s, + &["admin", "developer"], + )), } } } diff --git a/crates/tower-api/src/models/invite_team_member_response.rs b/crates/tower-api/src/models/invite_team_member_response.rs index c0945027..fd2549d4 100644 --- a/crates/tower-api/src/models/invite_team_member_response.rs +++ b/crates/tower-api/src/models/invite_team_member_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/leave_team_response.rs b/crates/tower-api/src/models/leave_team_response.rs index 1fb7dc63..fe487b9e 100644 --- a/crates/tower-api/src/models/leave_team_response.rs +++ b/crates/tower-api/src/models/leave_team_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_alerts_response.rs b/crates/tower-api/src/models/list_alerts_response.rs index 6c420d3e..2071fd2a 100644 --- a/crates/tower-api/src/models/list_alerts_response.rs +++ b/crates/tower-api/src/models/list_alerts_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_api_keys_response.rs b/crates/tower-api/src/models/list_api_keys_response.rs index c42bcbd0..b1a12809 100644 --- a/crates/tower-api/src/models/list_api_keys_response.rs +++ b/crates/tower-api/src/models/list_api_keys_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_app_environments_response.rs b/crates/tower-api/src/models/list_app_environments_response.rs index 45c7ce8f..3e8b818b 100644 --- a/crates/tower-api/src/models/list_app_environments_response.rs +++ b/crates/tower-api/src/models/list_app_environments_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_app_versions_response.rs b/crates/tower-api/src/models/list_app_versions_response.rs index 1db80ce8..90eb8825 100644 --- a/crates/tower-api/src/models/list_app_versions_response.rs +++ b/crates/tower-api/src/models/list_app_versions_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_apps_response.rs b/crates/tower-api/src/models/list_apps_response.rs index 4e2b70cb..6bbedbe7 100644 --- a/crates/tower-api/src/models/list_apps_response.rs +++ b/crates/tower-api/src/models/list_apps_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_authenticators_response.rs b/crates/tower-api/src/models/list_authenticators_response.rs index 168ea98a..abe8503a 100644 --- a/crates/tower-api/src/models/list_authenticators_response.rs +++ b/crates/tower-api/src/models/list_authenticators_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_catalogs_response.rs b/crates/tower-api/src/models/list_catalogs_response.rs index cf4540fe..7657fcce 100644 --- a/crates/tower-api/src/models/list_catalogs_response.rs +++ b/crates/tower-api/src/models/list_catalogs_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_environments_response.rs b/crates/tower-api/src/models/list_environments_response.rs index dcc21d16..6a0cadc3 100644 --- a/crates/tower-api/src/models/list_environments_response.rs +++ b/crates/tower-api/src/models/list_environments_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_guests_response.rs b/crates/tower-api/src/models/list_guests_response.rs new file mode 100644 index 00000000..69df2672 --- /dev/null +++ b/crates/tower-api/src/models/list_guests_response.rs @@ -0,0 +1,33 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct ListGuestsResponse { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// List of guests. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "guests")] + pub guests: Vec, +} + +impl ListGuestsResponse { + pub fn new(guests: Vec) -> ListGuestsResponse { + ListGuestsResponse { + schema: None, + guests, + } + } +} diff --git a/crates/tower-api/src/models/list_my_team_invitations_response.rs b/crates/tower-api/src/models/list_my_team_invitations_response.rs index 0526baa8..5cd2f13f 100644 --- a/crates/tower-api/src/models/list_my_team_invitations_response.rs +++ b/crates/tower-api/src/models/list_my_team_invitations_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_runners_response.rs b/crates/tower-api/src/models/list_runners_response.rs index e2117737..832c3615 100644 --- a/crates/tower-api/src/models/list_runners_response.rs +++ b/crates/tower-api/src/models/list_runners_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_runs_response.rs b/crates/tower-api/src/models/list_runs_response.rs index d6b14a25..52913235 100644 --- a/crates/tower-api/src/models/list_runs_response.rs +++ b/crates/tower-api/src/models/list_runs_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_schedules_response.rs b/crates/tower-api/src/models/list_schedules_response.rs index b8e84277..84da5875 100644 --- a/crates/tower-api/src/models/list_schedules_response.rs +++ b/crates/tower-api/src/models/list_schedules_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_secret_environments_response.rs b/crates/tower-api/src/models/list_secret_environments_response.rs index f316531e..d2ffc0df 100644 --- a/crates/tower-api/src/models/list_secret_environments_response.rs +++ b/crates/tower-api/src/models/list_secret_environments_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_secrets_response.rs b/crates/tower-api/src/models/list_secrets_response.rs index 9830b563..10a7db77 100644 --- a/crates/tower-api/src/models/list_secrets_response.rs +++ b/crates/tower-api/src/models/list_secrets_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_team_invitations_response.rs b/crates/tower-api/src/models/list_team_invitations_response.rs index 1efe24c6..7cdb3b52 100644 --- a/crates/tower-api/src/models/list_team_invitations_response.rs +++ b/crates/tower-api/src/models/list_team_invitations_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_team_members_response.rs b/crates/tower-api/src/models/list_team_members_response.rs index db467231..7cde67a7 100644 --- a/crates/tower-api/src/models/list_team_members_response.rs +++ b/crates/tower-api/src/models/list_team_members_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_teams_response.rs b/crates/tower-api/src/models/list_teams_response.rs index 6d5b727c..4493e7ee 100644 --- a/crates/tower-api/src/models/list_teams_response.rs +++ b/crates/tower-api/src/models/list_teams_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/list_webhooks_response.rs b/crates/tower-api/src/models/list_webhooks_response.rs index b9a8beaf..991acb5f 100644 --- a/crates/tower-api/src/models/list_webhooks_response.rs +++ b/crates/tower-api/src/models/list_webhooks_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/mod.rs b/crates/tower-api/src/models/mod.rs index d9be66e5..400fb7cb 100644 --- a/crates/tower-api/src/models/mod.rs +++ b/crates/tower-api/src/models/mod.rs @@ -60,6 +60,10 @@ pub mod create_environment_params; pub use self::create_environment_params::CreateEnvironmentParams; pub mod create_environment_response; pub use self::create_environment_response::CreateEnvironmentResponse; +pub mod create_guest_params; +pub use self::create_guest_params::CreateGuestParams; +pub mod create_guest_response; +pub use self::create_guest_response::CreateGuestResponse; pub mod create_password_reset_params; pub use self::create_password_reset_params::CreatePasswordResetParams; pub mod create_password_reset_response; @@ -100,6 +104,8 @@ pub mod delete_authenticator_response; pub use self::delete_authenticator_response::DeleteAuthenticatorResponse; pub mod delete_catalog_response; pub use self::delete_catalog_response::DeleteCatalogResponse; +pub mod delete_guest_output_body; +pub use self::delete_guest_output_body::DeleteGuestOutputBody; pub mod delete_schedule_params; pub use self::delete_schedule_params::DeleteScheduleParams; pub mod delete_schedule_response; @@ -132,6 +138,8 @@ pub mod describe_app_version_response; pub use self::describe_app_version_response::DescribeAppVersionResponse; pub mod describe_authentication_context_body; pub use self::describe_authentication_context_body::DescribeAuthenticationContextBody; +pub mod describe_catalog_response; +pub use self::describe_catalog_response::DescribeCatalogResponse; pub mod describe_device_login_session_response; pub use self::describe_device_login_session_response::DescribeDeviceLoginSessionResponse; pub mod describe_email_preferences_body; @@ -202,6 +210,8 @@ pub mod generate_runner_credentials_response; pub use self::generate_runner_credentials_response::GenerateRunnerCredentialsResponse; pub mod get_feature_flag_response_body; pub use self::get_feature_flag_response_body::GetFeatureFlagResponseBody; +pub mod guest; +pub use self::guest::Guest; pub mod invite_team_member_params; pub use self::invite_team_member_params::InviteTeamMemberParams; pub mod invite_team_member_response; @@ -224,6 +234,8 @@ pub mod list_catalogs_response; pub use self::list_catalogs_response::ListCatalogsResponse; pub mod list_environments_response; pub use self::list_environments_response::ListEnvironmentsResponse; +pub mod list_guests_response; +pub use self::list_guests_response::ListGuestsResponse; pub mod list_my_team_invitations_response; pub use self::list_my_team_invitations_response::ListMyTeamInvitationsResponse; pub mod list_runners_response; @@ -246,6 +258,8 @@ pub mod list_webhooks_response; pub use self::list_webhooks_response::ListWebhooksResponse; pub mod organization; pub use self::organization::Organization; +pub mod organization_usage; +pub use self::organization_usage::OrganizationUsage; pub mod pagination; pub use self::pagination::Pagination; pub mod parameter; @@ -256,6 +270,10 @@ pub mod refresh_session_params; pub use self::refresh_session_params::RefreshSessionParams; pub mod refresh_session_response; pub use self::refresh_session_response::RefreshSessionResponse; +pub mod regenerate_guest_login_url_params; +pub use self::regenerate_guest_login_url_params::RegenerateGuestLoginUrlParams; +pub mod regenerate_guest_login_url_response; +pub use self::regenerate_guest_login_url_response::RegenerateGuestLoginUrlResponse; pub mod remove_team_member_params; pub use self::remove_team_member_params::RemoveTeamMemberParams; pub mod remove_team_member_response; @@ -272,6 +290,8 @@ pub mod run_app_params; pub use self::run_app_params::RunAppParams; pub mod run_app_response; pub use self::run_app_response::RunAppResponse; +pub mod run_attempt; +pub use self::run_attempt::RunAttempt; pub mod run_failure_alert; pub use self::run_failure_alert::RunFailureAlert; pub mod run_graph_node; @@ -288,6 +308,8 @@ pub mod run_parameter; pub use self::run_parameter::RunParameter; pub mod run_results; pub use self::run_results::RunResults; +pub mod run_retry_policy; +pub use self::run_retry_policy::RunRetryPolicy; pub mod run_run_initiator_details; pub use self::run_run_initiator_details::RunRunInitiatorDetails; pub mod run_statistics; @@ -390,6 +412,8 @@ pub mod update_webhook_params; pub use self::update_webhook_params::UpdateWebhookParams; pub mod update_webhook_response; pub use self::update_webhook_response::UpdateWebhookResponse; +pub mod usage_limit; +pub use self::usage_limit::UsageLimit; pub mod user; pub use self::user::User; pub mod verified_authenticator; diff --git a/crates/tower-api/src/models/organization.rs b/crates/tower-api/src/models/organization.rs index c49734da..45d76a6a 100644 --- a/crates/tower-api/src/models/organization.rs +++ b/crates/tower-api/src/models/organization.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/organization_usage.rs b/crates/tower-api/src/models/organization_usage.rs new file mode 100644 index 00000000..be468329 --- /dev/null +++ b/crates/tower-api/src/models/organization_usage.rs @@ -0,0 +1,71 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct OrganizationUsage { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// Number of active schedules in the organization. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "active_schedules")] + pub active_schedules: models::UsageLimit, + /// Number of applications in the organization. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "apps")] + pub apps: models::UsageLimit, + /// The name of the organization's base plan. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "base_plan_name")] + pub base_plan_name: String, + /// Number of compute minutes used in the current billing cycle. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "compute_minutes")] + pub compute_minutes: models::UsageLimit, + /// Number of users in the organization. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "members")] + pub members: models::UsageLimit, + /// The name of the organization. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "organization_name")] + pub organization_name: String, + /// Whether the organization has the ability to use self-hosted runners. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "self_hosted_runners")] + pub self_hosted_runners: models::UsageLimit, +} + +impl OrganizationUsage { + pub fn new( + active_schedules: models::UsageLimit, + apps: models::UsageLimit, + base_plan_name: String, + compute_minutes: models::UsageLimit, + members: models::UsageLimit, + organization_name: String, + self_hosted_runners: models::UsageLimit, + ) -> OrganizationUsage { + OrganizationUsage { + schema: None, + active_schedules, + apps, + base_plan_name, + compute_minutes, + members, + organization_name, + self_hosted_runners, + } + } +} diff --git a/crates/tower-api/src/models/pagination.rs b/crates/tower-api/src/models/pagination.rs index 38152eb0..4690dadc 100644 --- a/crates/tower-api/src/models/pagination.rs +++ b/crates/tower-api/src/models/pagination.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/parameter.rs b/crates/tower-api/src/models/parameter.rs index f53c7b45..9b67aa00 100644 --- a/crates/tower-api/src/models/parameter.rs +++ b/crates/tower-api/src/models/parameter.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -20,12 +20,12 @@ pub struct Parameter { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "description")] pub description: String, + /// Whether this parameter is hidden/secret. Defaults to false. + #[serde(rename = "hidden", skip_serializing_if = "Option::is_none")] + pub hidden: Option, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "name")] pub name: String, - #[serde(default)] - #[serde(rename = "hidden")] - pub hidden: bool, } impl Parameter { @@ -33,8 +33,8 @@ impl Parameter { Parameter { default, description, + hidden: None, name, - hidden: false, } } } diff --git a/crates/tower-api/src/models/plan.rs b/crates/tower-api/src/models/plan.rs index cce31a82..7ee275fa 100644 --- a/crates/tower-api/src/models/plan.rs +++ b/crates/tower-api/src/models/plan.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/refresh_session_params.rs b/crates/tower-api/src/models/refresh_session_params.rs index 0f7c6018..e266c28c 100644 --- a/crates/tower-api/src/models/refresh_session_params.rs +++ b/crates/tower-api/src/models/refresh_session_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/refresh_session_response.rs b/crates/tower-api/src/models/refresh_session_response.rs index 2531a9e9..9d60d979 100644 --- a/crates/tower-api/src/models/refresh_session_response.rs +++ b/crates/tower-api/src/models/refresh_session_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/regenerate_guest_login_url_params.rs b/crates/tower-api/src/models/regenerate_guest_login_url_params.rs new file mode 100644 index 00000000..df3a96ba --- /dev/null +++ b/crates/tower-api/src/models/regenerate_guest_login_url_params.rs @@ -0,0 +1,36 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct RegenerateGuestLoginUrlParams { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// The number of seconds the guest session should last. Defaults to 72 hours. + #[serde(rename = "expires_in", skip_serializing_if = "Option::is_none")] + pub expires_in: Option, + /// Where to redirect the guest after they log in. + #[serde(rename = "redirect_url", skip_serializing_if = "Option::is_none")] + pub redirect_url: Option, +} + +impl RegenerateGuestLoginUrlParams { + pub fn new() -> RegenerateGuestLoginUrlParams { + RegenerateGuestLoginUrlParams { + schema: None, + expires_in: None, + redirect_url: None, + } + } +} diff --git a/crates/tower-api/src/models/regenerate_guest_login_url_response.rs b/crates/tower-api/src/models/regenerate_guest_login_url_response.rs new file mode 100644 index 00000000..c4dcd87d --- /dev/null +++ b/crates/tower-api/src/models/regenerate_guest_login_url_response.rs @@ -0,0 +1,38 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct RegenerateGuestLoginUrlResponse { + /// A URL to the JSON Schema for this object. + #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] + pub schema: Option, + /// The new login URL to share with the guest. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "login_url")] + pub login_url: String, + /// When the login URL expires. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "login_url_expires_at")] + pub login_url_expires_at: String, +} + +impl RegenerateGuestLoginUrlResponse { + pub fn new(login_url: String, login_url_expires_at: String) -> RegenerateGuestLoginUrlResponse { + RegenerateGuestLoginUrlResponse { + schema: None, + login_url, + login_url_expires_at, + } + } +} diff --git a/crates/tower-api/src/models/remove_team_member_params.rs b/crates/tower-api/src/models/remove_team_member_params.rs index 530f445a..8ac73f71 100644 --- a/crates/tower-api/src/models/remove_team_member_params.rs +++ b/crates/tower-api/src/models/remove_team_member_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/remove_team_member_response.rs b/crates/tower-api/src/models/remove_team_member_response.rs index c92005cf..725ab75d 100644 --- a/crates/tower-api/src/models/remove_team_member_response.rs +++ b/crates/tower-api/src/models/remove_team_member_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/resend_team_invitation_params.rs b/crates/tower-api/src/models/resend_team_invitation_params.rs index 4903d77b..47954247 100644 --- a/crates/tower-api/src/models/resend_team_invitation_params.rs +++ b/crates/tower-api/src/models/resend_team_invitation_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/resend_team_invitation_response.rs b/crates/tower-api/src/models/resend_team_invitation_response.rs index c23b921f..196056eb 100644 --- a/crates/tower-api/src/models/resend_team_invitation_response.rs +++ b/crates/tower-api/src/models/resend_team_invitation_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run.rs b/crates/tower-api/src/models/run.rs index 05d6b77b..e6d6d936 100644 --- a/crates/tower-api/src/models/run.rs +++ b/crates/tower-api/src/models/run.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -27,6 +27,9 @@ pub struct Run { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "app_version")] pub app_version: String, + /// Previous attempt details. Populated on describe, omitted on list. + #[serde(rename = "attempts", skip_serializing_if = "Option::is_none")] + pub attempts: Option>, #[serde(rename = "cancelled_at", deserialize_with = "Option::deserialize")] pub cancelled_at: Option, #[serde_as(as = "DefaultOnNull")] @@ -51,6 +54,10 @@ pub struct Run { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "is_scheduled")] pub is_scheduled: bool, + /// Number of attempts for this run (1 = original, 2+ = retries). + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "num_attempts")] + pub num_attempts: i64, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "number")] pub number: i64, @@ -58,6 +65,9 @@ pub struct Run { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "parameters")] pub parameters: Vec, + /// Retry policy configured for this run. + #[serde(rename = "retry_policy", skip_serializing_if = "Option::is_none")] + pub retry_policy: Option, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "run_id")] pub run_id: String, @@ -94,6 +104,7 @@ impl Run { exit_code: Option, initiator: models::RunInitiator, is_scheduled: bool, + num_attempts: i64, number: i64, parameters: Vec, run_id: String, @@ -107,6 +118,7 @@ impl Run { app_name, app_slug: None, app_version, + attempts: None, cancelled_at, created_at, ended_at, @@ -115,8 +127,10 @@ impl Run { hostname: None, initiator, is_scheduled, + num_attempts, number, parameters, + retry_policy: None, run_id, scheduled_at, started_at, @@ -131,6 +145,8 @@ impl Run { pub enum Status { #[serde(rename = "scheduled")] Scheduled, + #[serde(rename = "retrying")] + Retrying, #[serde(rename = "pending")] Pending, #[serde(rename = "running")] @@ -159,6 +175,7 @@ impl<'de> Deserialize<'de> for Status { let s = String::deserialize(deserializer)?; match s.to_lowercase().as_str() { "scheduled" => Ok(Self::Scheduled), + "retrying" => Ok(Self::Retrying), "pending" => Ok(Self::Pending), "running" => Ok(Self::Running), "crashed" => Ok(Self::Crashed), @@ -169,6 +186,7 @@ impl<'de> Deserialize<'de> for Status { &s, &[ "scheduled", + "retrying", "pending", "running", "crashed", diff --git a/crates/tower-api/src/models/run_app_initiator_data.rs b/crates/tower-api/src/models/run_app_initiator_data.rs index d6ec46ac..ae89420e 100644 --- a/crates/tower-api/src/models/run_app_initiator_data.rs +++ b/crates/tower-api/src/models/run_app_initiator_data.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_app_params.rs b/crates/tower-api/src/models/run_app_params.rs index e25cf4ac..0f577318 100644 --- a/crates/tower-api/src/models/run_app_params.rs +++ b/crates/tower-api/src/models/run_app_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -36,6 +36,9 @@ pub struct RunAppParams { skip_serializing_if = "Option::is_none" )] pub parent_run_id: Option>, + /// Override the retry policy for this specific run. If not provided, inherits from the app's retry policy. + #[serde(rename = "retry_policy", skip_serializing_if = "Option::is_none")] + pub retry_policy: Option, } impl RunAppParams { @@ -49,6 +52,7 @@ impl RunAppParams { initiator: None, parameters, parent_run_id: None, + retry_policy: None, } } } diff --git a/crates/tower-api/src/models/run_app_response.rs b/crates/tower-api/src/models/run_app_response.rs index 3629632f..ee1b8e7e 100644 --- a/crates/tower-api/src/models/run_app_response.rs +++ b/crates/tower-api/src/models/run_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_attempt.rs b/crates/tower-api/src/models/run_attempt.rs new file mode 100644 index 00000000..32ff62e2 --- /dev/null +++ b/crates/tower-api/src/models/run_attempt.rs @@ -0,0 +1,52 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct RunAttempt { + /// When this attempt ended. + #[serde(rename = "ended_at", deserialize_with = "Option::deserialize")] + pub ended_at: Option, + /// Exit code for this attempt. + #[serde(rename = "exit_code", deserialize_with = "Option::deserialize")] + pub exit_code: Option, + /// 1-based attempt number. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "seq")] + pub seq: i64, + /// When this attempt started. + #[serde(rename = "started_at", deserialize_with = "Option::deserialize")] + pub started_at: Option, + /// Terminal status of this attempt. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "status")] + pub status: String, +} + +impl RunAttempt { + pub fn new( + ended_at: Option, + exit_code: Option, + seq: i64, + started_at: Option, + status: String, + ) -> RunAttempt { + RunAttempt { + ended_at, + exit_code, + seq, + started_at, + status, + } + } +} diff --git a/crates/tower-api/src/models/run_failure_alert.rs b/crates/tower-api/src/models/run_failure_alert.rs index 6d2c18f9..8a49854c 100644 --- a/crates/tower-api/src/models/run_failure_alert.rs +++ b/crates/tower-api/src/models/run_failure_alert.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_graph_node.rs b/crates/tower-api/src/models/run_graph_node.rs index 0b74c36a..3cc5117f 100644 --- a/crates/tower-api/src/models/run_graph_node.rs +++ b/crates/tower-api/src/models/run_graph_node.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_graph_run_id.rs b/crates/tower-api/src/models/run_graph_run_id.rs index 01c02873..727bd13e 100644 --- a/crates/tower-api/src/models/run_graph_run_id.rs +++ b/crates/tower-api/src/models/run_graph_run_id.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_initiator.rs b/crates/tower-api/src/models/run_initiator.rs index 5a6764bc..17a04ff3 100644 --- a/crates/tower-api/src/models/run_initiator.rs +++ b/crates/tower-api/src/models/run_initiator.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_initiator_details.rs b/crates/tower-api/src/models/run_initiator_details.rs index f269868f..6c293f48 100644 --- a/crates/tower-api/src/models/run_initiator_details.rs +++ b/crates/tower-api/src/models/run_initiator_details.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_log_line.rs b/crates/tower-api/src/models/run_log_line.rs index a2e48743..2ec70bfb 100644 --- a/crates/tower-api/src/models/run_log_line.rs +++ b/crates/tower-api/src/models/run_log_line.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -14,6 +14,10 @@ use serde_with::{serde_as, DefaultOnNull}; #[serde_as] #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct RunLogLine { + /// The attempt number this log line belongs to (1-based). Attempt 1 is the original execution; 2+ are retries. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "attempt_seq")] + pub attempt_seq: i64, /// The channel this log line belongs to. #[serde_as(as = "DefaultOnNull")] #[serde(rename = "channel")] @@ -44,6 +48,7 @@ pub struct RunLogLine { impl RunLogLine { pub fn new( + attempt_seq: i64, channel: Channel, content: String, line_num: i64, @@ -51,6 +56,7 @@ impl RunLogLine { run_id: String, ) -> RunLogLine { RunLogLine { + attempt_seq, channel, content, line_num, diff --git a/crates/tower-api/src/models/run_parameter.rs b/crates/tower-api/src/models/run_parameter.rs index f45cc23d..42618065 100644 --- a/crates/tower-api/src/models/run_parameter.rs +++ b/crates/tower-api/src/models/run_parameter.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -14,23 +14,23 @@ use serde_with::{serde_as, DefaultOnNull}; #[serde_as] #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct RunParameter { + /// Whether this parameter is hidden/secret. Defaults to false. + #[serde(rename = "hidden", skip_serializing_if = "Option::is_none")] + pub hidden: Option, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "name")] pub name: String, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "value")] pub value: String, - #[serde(default)] - #[serde(rename = "hidden")] - pub hidden: bool, } impl RunParameter { pub fn new(name: String, value: String) -> RunParameter { RunParameter { + hidden: None, name, value, - hidden: false, } } } diff --git a/crates/tower-api/src/models/run_results.rs b/crates/tower-api/src/models/run_results.rs index 1c3bf7c2..9bd3ac5f 100644 --- a/crates/tower-api/src/models/run_results.rs +++ b/crates/tower-api/src/models/run_results.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -30,6 +30,9 @@ pub struct RunResults { #[serde(rename = "pending")] pub pending: i64, #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "retrying")] + pub retrying: i64, + #[serde_as(as = "DefaultOnNull")] #[serde(rename = "running")] pub running: i64, } @@ -41,6 +44,7 @@ impl RunResults { errored: i64, exited: i64, pending: i64, + retrying: i64, running: i64, ) -> RunResults { RunResults { @@ -49,6 +53,7 @@ impl RunResults { errored, exited, pending, + retrying, running, } } diff --git a/crates/tower-api/src/models/run_retry_policy.rs b/crates/tower-api/src/models/run_retry_policy.rs new file mode 100644 index 00000000..0bcfba16 --- /dev/null +++ b/crates/tower-api/src/models/run_retry_policy.rs @@ -0,0 +1,40 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct RunRetryPolicy { + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "max_retries")] + pub max_retries: i64, + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "retry_delay_seconds")] + pub retry_delay_seconds: i64, + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "use_exponential_backoff")] + pub use_exponential_backoff: bool, +} + +impl RunRetryPolicy { + pub fn new( + max_retries: i64, + retry_delay_seconds: i64, + use_exponential_backoff: bool, + ) -> RunRetryPolicy { + RunRetryPolicy { + max_retries, + retry_delay_seconds, + use_exponential_backoff, + } + } +} diff --git a/crates/tower-api/src/models/run_run_initiator_details.rs b/crates/tower-api/src/models/run_run_initiator_details.rs index 9ea88ae3..d81055bf 100644 --- a/crates/tower-api/src/models/run_run_initiator_details.rs +++ b/crates/tower-api/src/models/run_run_initiator_details.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_statistics.rs b/crates/tower-api/src/models/run_statistics.rs index 179ec833..fc905396 100644 --- a/crates/tower-api/src/models/run_statistics.rs +++ b/crates/tower-api/src/models/run_statistics.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/run_timeseries_point.rs b/crates/tower-api/src/models/run_timeseries_point.rs index 3dfb8677..87f4ace4 100644 --- a/crates/tower-api/src/models/run_timeseries_point.rs +++ b/crates/tower-api/src/models/run_timeseries_point.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -34,6 +34,9 @@ pub struct RunTimeseriesPoint { #[serde(rename = "period")] pub period: String, #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "retrying")] + pub retrying: i64, + #[serde_as(as = "DefaultOnNull")] #[serde(rename = "running")] pub running: i64, #[serde_as(as = "DefaultOnNull")] @@ -49,6 +52,7 @@ impl RunTimeseriesPoint { exited: i64, pending: i64, period: String, + retrying: i64, running: i64, scheduled: i64, ) -> RunTimeseriesPoint { @@ -59,6 +63,7 @@ impl RunTimeseriesPoint { exited, pending, period, + retrying, running, scheduled, } diff --git a/crates/tower-api/src/models/runner.rs b/crates/tower-api/src/models/runner.rs index ef57c86d..71167f77 100644 --- a/crates/tower-api/src/models/runner.rs +++ b/crates/tower-api/src/models/runner.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -31,6 +31,9 @@ pub struct Runner { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "max_concurrent_apps")] pub max_concurrent_apps: i64, + /// Optional human-readable name for the runner + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "num_runs")] pub num_runs: i64, @@ -54,6 +57,7 @@ impl Runner { id, last_health_check_at: None, max_concurrent_apps, + name: None, num_runs, status, } diff --git a/crates/tower-api/src/models/runner_credentials.rs b/crates/tower-api/src/models/runner_credentials.rs index cae80f25..d1142f4c 100644 --- a/crates/tower-api/src/models/runner_credentials.rs +++ b/crates/tower-api/src/models/runner_credentials.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/schedule.rs b/crates/tower-api/src/models/schedule.rs index db22c0da..24072405 100644 --- a/crates/tower-api/src/models/schedule.rs +++ b/crates/tower-api/src/models/schedule.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -56,6 +56,10 @@ pub struct Schedule { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "status")] pub status: Status, + /// The IANA timezone identifier that the cron expression is evaluated in (e.g., 'America/New_York', 'Europe/London'). Defaults to 'UTC'. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "timezone")] + pub timezone: String, /// The timestamp when the schedule was last updated #[serde_as(as = "DefaultOnNull")] #[serde(rename = "updated_at")] @@ -73,6 +77,7 @@ impl Schedule { name: String, overlap_policy: OverlapPolicy, status: Status, + timezone: String, updated_at: String, ) -> Schedule { Schedule { @@ -87,6 +92,7 @@ impl Schedule { overlap_policy, parameters: None, status, + timezone, updated_at, } } diff --git a/crates/tower-api/src/models/schedule_run_initiator_details.rs b/crates/tower-api/src/models/schedule_run_initiator_details.rs index 111bb75a..23f7bfc3 100644 --- a/crates/tower-api/src/models/schedule_run_initiator_details.rs +++ b/crates/tower-api/src/models/schedule_run_initiator_details.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/search_runs_response.rs b/crates/tower-api/src/models/search_runs_response.rs index 7b993386..3ab7e8a6 100644 --- a/crates/tower-api/src/models/search_runs_response.rs +++ b/crates/tower-api/src/models/search_runs_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/secret.rs b/crates/tower-api/src/models/secret.rs index bf12b88f..039f872f 100644 --- a/crates/tower-api/src/models/secret.rs +++ b/crates/tower-api/src/models/secret.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/server_sent_events_inner.rs b/crates/tower-api/src/models/server_sent_events_inner.rs index 1a4794e4..ce0517b6 100644 --- a/crates/tower-api/src/models/server_sent_events_inner.rs +++ b/crates/tower-api/src/models/server_sent_events_inner.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/server_sent_events_inner_1.rs b/crates/tower-api/src/models/server_sent_events_inner_1.rs index a2b2c568..522bef18 100644 --- a/crates/tower-api/src/models/server_sent_events_inner_1.rs +++ b/crates/tower-api/src/models/server_sent_events_inner_1.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/server_sent_events_inner_2.rs b/crates/tower-api/src/models/server_sent_events_inner_2.rs index 04624679..8557e17d 100644 --- a/crates/tower-api/src/models/server_sent_events_inner_2.rs +++ b/crates/tower-api/src/models/server_sent_events_inner_2.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/session.rs b/crates/tower-api/src/models/session.rs index 7adcfa55..b8980f3c 100644 --- a/crates/tower-api/src/models/session.rs +++ b/crates/tower-api/src/models/session.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/shoulder_tap.rs b/crates/tower-api/src/models/shoulder_tap.rs index 5badb842..504d0cfa 100644 --- a/crates/tower-api/src/models/shoulder_tap.rs +++ b/crates/tower-api/src/models/shoulder_tap.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/sse_warning.rs b/crates/tower-api/src/models/sse_warning.rs index f2b9e64e..b75136b2 100644 --- a/crates/tower-api/src/models/sse_warning.rs +++ b/crates/tower-api/src/models/sse_warning.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/statistics_settings.rs b/crates/tower-api/src/models/statistics_settings.rs index 815bd280..c49eefe1 100644 --- a/crates/tower-api/src/models/statistics_settings.rs +++ b/crates/tower-api/src/models/statistics_settings.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/team.rs b/crates/tower-api/src/models/team.rs index cf47722f..d1dfc5af 100644 --- a/crates/tower-api/src/models/team.rs +++ b/crates/tower-api/src/models/team.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -14,9 +14,16 @@ use serde_with::{serde_as, DefaultOnNull}; #[serde_as] #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct Team { + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "execution_region")] + pub execution_region: String, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "name")] pub name: String, + /// The name of the organization this team belongs to. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "organization")] + pub organization: String, /// This property is deprecated. Use name instead. #[serde(rename = "slug", skip_serializing_if = "Option::is_none")] pub slug: Option, @@ -29,9 +36,16 @@ pub struct Team { } impl Team { - pub fn new(name: String, r#type: String) -> Team { + pub fn new( + execution_region: String, + name: String, + organization: String, + r#type: String, + ) -> Team { Team { + execution_region, name, + organization, slug: None, token: None, r#type, diff --git a/crates/tower-api/src/models/team_invitation.rs b/crates/tower-api/src/models/team_invitation.rs index 3c724374..e2f869ca 100644 --- a/crates/tower-api/src/models/team_invitation.rs +++ b/crates/tower-api/src/models/team_invitation.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -20,31 +20,26 @@ pub struct TeamInvitation { #[serde_as(as = "DefaultOnNull")] #[serde(rename = "invitation_sent_at")] pub invitation_sent_at: String, - /// The name of the organization the user will move to if they accept this invitation - #[serde( - rename = "target_organization_name", - skip_serializing_if = "Option::is_none" - )] - pub target_organization_name: Option, + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "role")] + pub role: String, #[serde_as(as = "DefaultOnNull")] #[serde(rename = "team")] pub team: models::Team, - /// Indicates if accepting this invitation will move the user to a different organization - #[serde( - rename = "will_change_organization", - skip_serializing_if = "Option::is_none" - )] - pub will_change_organization: Option, } impl TeamInvitation { - pub fn new(email: String, invitation_sent_at: String, team: models::Team) -> TeamInvitation { + pub fn new( + email: String, + invitation_sent_at: String, + role: String, + team: models::Team, + ) -> TeamInvitation { TeamInvitation { email, invitation_sent_at, - target_organization_name: None, + role, team, - will_change_organization: None, } } } diff --git a/crates/tower-api/src/models/team_membership.rs b/crates/tower-api/src/models/team_membership.rs index 478a4849..7ff50630 100644 --- a/crates/tower-api/src/models/team_membership.rs +++ b/crates/tower-api/src/models/team_membership.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/test_webhook_response.rs b/crates/tower-api/src/models/test_webhook_response.rs index 9ac0d341..e914e4f7 100644 --- a/crates/tower-api/src/models/test_webhook_response.rs +++ b/crates/tower-api/src/models/test_webhook_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/token.rs b/crates/tower-api/src/models/token.rs index aaaa1741..a014e283 100644 --- a/crates/tower-api/src/models/token.rs +++ b/crates/tower-api/src/models/token.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/unverified_authenticator.rs b/crates/tower-api/src/models/unverified_authenticator.rs index 1427188f..d78f878a 100644 --- a/crates/tower-api/src/models/unverified_authenticator.rs +++ b/crates/tower-api/src/models/unverified_authenticator.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_account_params.rs b/crates/tower-api/src/models/update_account_params.rs index 274302f7..b740b803 100644 --- a/crates/tower-api/src/models/update_account_params.rs +++ b/crates/tower-api/src/models/update_account_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -17,6 +17,9 @@ pub struct UpdateAccountParams { /// A URL to the JSON Schema for this object. #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] pub schema: Option, + /// The execution region for runs (eu-central-1 or us-east-1) + #[serde(rename = "execution_region", skip_serializing_if = "Option::is_none")] + pub execution_region: Option, /// Whether the account is for self-hosted use only #[serde( rename = "is_self_hosted_only", @@ -32,8 +35,40 @@ impl UpdateAccountParams { pub fn new() -> UpdateAccountParams { UpdateAccountParams { schema: None, + execution_region: None, is_self_hosted_only: None, name: None, } } } +/// The execution region for runs (eu-central-1 or us-east-1) +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +pub enum ExecutionRegion { + #[serde(rename = "eu-central-1")] + EuCentral1, + #[serde(rename = "us-east-1")] + UsEast1, +} + +impl Default for ExecutionRegion { + fn default() -> ExecutionRegion { + Self::EuCentral1 + } +} + +impl<'de> Deserialize<'de> for ExecutionRegion { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + match s.to_lowercase().as_str() { + "eu-central-1" => Ok(Self::EuCentral1), + "us-east-1" => Ok(Self::UsEast1), + _ => Err(serde::de::Error::unknown_variant( + &s, + &["eu-central-1", "us-east-1"], + )), + } + } +} diff --git a/crates/tower-api/src/models/update_account_response.rs b/crates/tower-api/src/models/update_account_response.rs index 78643cb5..bf7c0b39 100644 --- a/crates/tower-api/src/models/update_account_response.rs +++ b/crates/tower-api/src/models/update_account_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_app_params.rs b/crates/tower-api/src/models/update_app_params.rs index 08f099f1..96403b8d 100644 --- a/crates/tower-api/src/models/update_app_params.rs +++ b/crates/tower-api/src/models/update_app_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -41,6 +41,9 @@ pub struct UpdateAppParams { skip_serializing_if = "Option::is_none" )] pub pending_timeout: Option>, + /// The retry policy for failed runs of this app. Defines different retry behavior for infrastructure (errored) vs application (crashed) failures. + #[serde(rename = "retry_policy", skip_serializing_if = "Option::is_none")] + pub retry_policy: Option, /// The amount of time in seconds that runs of this app can stay in running state before being marked as failed. #[serde( rename = "running_timeout", @@ -74,6 +77,7 @@ impl UpdateAppParams { description: None, is_externally_accessible: None, pending_timeout: None, + retry_policy: None, running_timeout: None, status: None, subdomain: None, diff --git a/crates/tower-api/src/models/update_app_response.rs b/crates/tower-api/src/models/update_app_response.rs index 07ac2631..96a41567 100644 --- a/crates/tower-api/src/models/update_app_response.rs +++ b/crates/tower-api/src/models/update_app_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_catalog_params.rs b/crates/tower-api/src/models/update_catalog_params.rs index 113e73dc..c0b9461f 100644 --- a/crates/tower-api/src/models/update_catalog_params.rs +++ b/crates/tower-api/src/models/update_catalog_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_catalog_response.rs b/crates/tower-api/src/models/update_catalog_response.rs index 93667482..d8cc3f88 100644 --- a/crates/tower-api/src/models/update_catalog_response.rs +++ b/crates/tower-api/src/models/update_catalog_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_email_preferences_body.rs b/crates/tower-api/src/models/update_email_preferences_body.rs index 4130765a..0786173b 100644 --- a/crates/tower-api/src/models/update_email_preferences_body.rs +++ b/crates/tower-api/src/models/update_email_preferences_body.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_environment_params.rs b/crates/tower-api/src/models/update_environment_params.rs index 39c3e8dc..7eb9a9e7 100644 --- a/crates/tower-api/src/models/update_environment_params.rs +++ b/crates/tower-api/src/models/update_environment_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_environment_response.rs b/crates/tower-api/src/models/update_environment_response.rs index f22feb5d..ddcea53a 100644 --- a/crates/tower-api/src/models/update_environment_response.rs +++ b/crates/tower-api/src/models/update_environment_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_my_team_invitation_params.rs b/crates/tower-api/src/models/update_my_team_invitation_params.rs index 33a5efe2..c811cc5d 100644 --- a/crates/tower-api/src/models/update_my_team_invitation_params.rs +++ b/crates/tower-api/src/models/update_my_team_invitation_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_my_team_invitation_response.rs b/crates/tower-api/src/models/update_my_team_invitation_response.rs index 99e08916..6a4e6347 100644 --- a/crates/tower-api/src/models/update_my_team_invitation_response.rs +++ b/crates/tower-api/src/models/update_my_team_invitation_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_organization_params.rs b/crates/tower-api/src/models/update_organization_params.rs index a63b9e25..d9817d39 100644 --- a/crates/tower-api/src/models/update_organization_params.rs +++ b/crates/tower-api/src/models/update_organization_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_organization_response.rs b/crates/tower-api/src/models/update_organization_response.rs index 3e09bbbe..a656fd57 100644 --- a/crates/tower-api/src/models/update_organization_response.rs +++ b/crates/tower-api/src/models/update_organization_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_password_reset_params.rs b/crates/tower-api/src/models/update_password_reset_params.rs index 8da2c477..e1a95a80 100644 --- a/crates/tower-api/src/models/update_password_reset_params.rs +++ b/crates/tower-api/src/models/update_password_reset_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_password_reset_response.rs b/crates/tower-api/src/models/update_password_reset_response.rs index a70ae3bc..37775127 100644 --- a/crates/tower-api/src/models/update_password_reset_response.rs +++ b/crates/tower-api/src/models/update_password_reset_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_plan_params.rs b/crates/tower-api/src/models/update_plan_params.rs index 646390ac..234b95b3 100644 --- a/crates/tower-api/src/models/update_plan_params.rs +++ b/crates/tower-api/src/models/update_plan_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_plan_response.rs b/crates/tower-api/src/models/update_plan_response.rs index 6c0a299d..9bfcc1ab 100644 --- a/crates/tower-api/src/models/update_plan_response.rs +++ b/crates/tower-api/src/models/update_plan_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_schedule_params.rs b/crates/tower-api/src/models/update_schedule_params.rs index 374f14b2..c28f3821 100644 --- a/crates/tower-api/src/models/update_schedule_params.rs +++ b/crates/tower-api/src/models/update_schedule_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -32,8 +32,13 @@ pub struct UpdateScheduleParams { #[serde(rename = "environment", skip_serializing_if = "Option::is_none")] pub environment: Option, /// The name for this schedule. Must be unique per team. - #[serde(rename = "name", deserialize_with = "Option::deserialize")] - pub name: Option, + #[serde( + rename = "name", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub name: Option>, /// The overlap policy for the schedule #[serde( rename = "overlap_policy", @@ -53,19 +58,28 @@ pub struct UpdateScheduleParams { skip_serializing_if = "Option::is_none" )] pub status: Option>, + /// The IANA timezone identifier that the cron expression should be evaluated in (e.g., 'America/New_York', 'Europe/London'). + #[serde( + rename = "timezone", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub timezone: Option>, } impl UpdateScheduleParams { - pub fn new(name: Option) -> UpdateScheduleParams { + pub fn new() -> UpdateScheduleParams { UpdateScheduleParams { schema: None, app_version: None, cron: None, environment: None, - name, + name: None, overlap_policy: None, parameters: None, status: None, + timezone: None, } } } diff --git a/crates/tower-api/src/models/update_schedule_response.rs b/crates/tower-api/src/models/update_schedule_response.rs index b06aa564..fe9e7fb5 100644 --- a/crates/tower-api/src/models/update_schedule_response.rs +++ b/crates/tower-api/src/models/update_schedule_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_secret_params.rs b/crates/tower-api/src/models/update_secret_params.rs index 2fcfd4a1..45f6f113 100644 --- a/crates/tower-api/src/models/update_secret_params.rs +++ b/crates/tower-api/src/models/update_secret_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_secret_response.rs b/crates/tower-api/src/models/update_secret_response.rs index 0c87f8ff..ca1f5d7d 100644 --- a/crates/tower-api/src/models/update_secret_response.rs +++ b/crates/tower-api/src/models/update_secret_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_team_member_params.rs b/crates/tower-api/src/models/update_team_member_params.rs index 1aa91336..6cf2beca 100644 --- a/crates/tower-api/src/models/update_team_member_params.rs +++ b/crates/tower-api/src/models/update_team_member_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_team_member_response.rs b/crates/tower-api/src/models/update_team_member_response.rs index 01855859..8425dd84 100644 --- a/crates/tower-api/src/models/update_team_member_response.rs +++ b/crates/tower-api/src/models/update_team_member_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_team_params.rs b/crates/tower-api/src/models/update_team_params.rs index 0132a2f1..4797291c 100644 --- a/crates/tower-api/src/models/update_team_params.rs +++ b/crates/tower-api/src/models/update_team_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ @@ -17,6 +17,9 @@ pub struct UpdateTeamParams { /// A URL to the JSON Schema for this object. #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] pub schema: Option, + /// The execution region for runs (eu-central-1 or us-east-1) + #[serde(rename = "execution_region", skip_serializing_if = "Option::is_none")] + pub execution_region: Option, /// The name of the team to update. This is optional, if you supply null it will not update the team name. #[serde(rename = "name", deserialize_with = "Option::deserialize")] pub name: Option, @@ -24,6 +27,41 @@ pub struct UpdateTeamParams { impl UpdateTeamParams { pub fn new(name: Option) -> UpdateTeamParams { - UpdateTeamParams { schema: None, name } + UpdateTeamParams { + schema: None, + execution_region: None, + name, + } + } +} +/// The execution region for runs (eu-central-1 or us-east-1) +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize)] +pub enum ExecutionRegion { + #[serde(rename = "eu-central-1")] + EuCentral1, + #[serde(rename = "us-east-1")] + UsEast1, +} + +impl Default for ExecutionRegion { + fn default() -> ExecutionRegion { + Self::EuCentral1 + } +} + +impl<'de> Deserialize<'de> for ExecutionRegion { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + match s.to_lowercase().as_str() { + "eu-central-1" => Ok(Self::EuCentral1), + "us-east-1" => Ok(Self::UsEast1), + _ => Err(serde::de::Error::unknown_variant( + &s, + &["eu-central-1", "us-east-1"], + )), + } } } diff --git a/crates/tower-api/src/models/update_team_response.rs b/crates/tower-api/src/models/update_team_response.rs index 59c43750..79be75bc 100644 --- a/crates/tower-api/src/models/update_team_response.rs +++ b/crates/tower-api/src/models/update_team_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_user_params.rs b/crates/tower-api/src/models/update_user_params.rs index a2626450..357260f3 100644 --- a/crates/tower-api/src/models/update_user_params.rs +++ b/crates/tower-api/src/models/update_user_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_user_response.rs b/crates/tower-api/src/models/update_user_response.rs index f751c75a..5b22df70 100644 --- a/crates/tower-api/src/models/update_user_response.rs +++ b/crates/tower-api/src/models/update_user_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_webhook_params.rs b/crates/tower-api/src/models/update_webhook_params.rs index 1d449de0..8c4b085d 100644 --- a/crates/tower-api/src/models/update_webhook_params.rs +++ b/crates/tower-api/src/models/update_webhook_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/update_webhook_response.rs b/crates/tower-api/src/models/update_webhook_response.rs index 3ea72f6d..b6b4e6b6 100644 --- a/crates/tower-api/src/models/update_webhook_response.rs +++ b/crates/tower-api/src/models/update_webhook_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/usage_limit.rs b/crates/tower-api/src/models/usage_limit.rs new file mode 100644 index 00000000..f5e70ebc --- /dev/null +++ b/crates/tower-api/src/models/usage_limit.rs @@ -0,0 +1,31 @@ +/* + * Tower API + * + * REST API to interact with Tower Services. + * + * The version of the OpenAPI document: v0.10.15 + * Contact: hello@tower.dev + * Generated by: https://openapi-generator.tech + */ +use crate::models; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, DefaultOnNull}; + +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct UsageLimit { + /// For numeric quotas: the maximum number of units allowed (-1 means unlimited). For boolean entitlements (e.g. self_hosted_runners): 0 = disabled, 1 = enabled. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "limit")] + pub limit: i64, + /// The number of units used for this resource. + #[serde_as(as = "DefaultOnNull")] + #[serde(rename = "used")] + pub used: i64, +} + +impl UsageLimit { + pub fn new(limit: i64, used: i64) -> UsageLimit { + UsageLimit { limit, used } + } +} diff --git a/crates/tower-api/src/models/user.rs b/crates/tower-api/src/models/user.rs index 9b1e01d3..7a1e84de 100644 --- a/crates/tower-api/src/models/user.rs +++ b/crates/tower-api/src/models/user.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/verified_authenticator.rs b/crates/tower-api/src/models/verified_authenticator.rs index 953722ae..0a14f1c2 100644 --- a/crates/tower-api/src/models/verified_authenticator.rs +++ b/crates/tower-api/src/models/verified_authenticator.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/verify_email_params.rs b/crates/tower-api/src/models/verify_email_params.rs index d2af772a..beb272d1 100644 --- a/crates/tower-api/src/models/verify_email_params.rs +++ b/crates/tower-api/src/models/verify_email_params.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/verify_email_response.rs b/crates/tower-api/src/models/verify_email_response.rs index d10f282b..165d2862 100644 --- a/crates/tower-api/src/models/verify_email_response.rs +++ b/crates/tower-api/src/models/verify_email_response.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-api/src/models/webhook.rs b/crates/tower-api/src/models/webhook.rs index 9931019e..f91d8b11 100644 --- a/crates/tower-api/src/models/webhook.rs +++ b/crates/tower-api/src/models/webhook.rs @@ -3,7 +3,7 @@ * * REST API to interact with Tower Services. * - * The version of the OpenAPI document: v0.9.29 + * The version of the OpenAPI document: v0.10.15 * Contact: hello@tower.dev * Generated by: https://openapi-generator.tech */ diff --git a/crates/tower-cmd/src/api.rs b/crates/tower-cmd/src/api.rs index f4b0a3c0..0297bf11 100644 --- a/crates/tower-cmd/src/api.rs +++ b/crates/tower-cmd/src/api.rs @@ -157,6 +157,7 @@ pub async fn run_app( parameters: params, parent_run_id: None, initiator: None, + retry_policy: None, }, }; @@ -219,6 +220,50 @@ pub async fn export_catalogs( .await } +pub async fn list_catalogs( + config: &Config, + env: &str, + all: bool, +) -> Result< + tower_api::models::ListCatalogsResponse, + Error, +> { + let api_config = &config.into(); + + let params = tower_api::apis::default_api::ListCatalogsParams { + environment: Some(env.to_string()), + all: Some(all), + page: None, + page_size: None, + }; + + unwrap_api_response(tower_api::apis::default_api::list_catalogs( + api_config, params, + )) + .await +} + +pub async fn describe_catalog( + config: &Config, + name: &str, + env: &str, +) -> Result< + tower_api::models::DescribeCatalogResponse, + Error, +> { + let api_config = &config.into(); + + let params = tower_api::apis::default_api::DescribeCatalogParams { + name: name.to_string(), + environment: Some(env.to_string()), + }; + + unwrap_api_response(tower_api::apis::default_api::describe_catalog( + api_config, params, + )) + .await +} + pub async fn list_secrets( config: &Config, env: &str, @@ -357,6 +402,22 @@ pub async fn refresh_session( .await } +pub async fn list_teams( + config: &Config, +) -> Result< + tower_api::models::ListTeamsResponse, + Error, +> { + let api_config = &config.into(); + + let params = tower_api::apis::default_api::ListTeamsParams { + page: None, + page_size: None, + }; + + unwrap_api_response(tower_api::apis::default_api::list_teams(api_config, params)).await +} + pub enum LogStreamEvent { EventLog(tower_api::models::RunLogLine), EventWarning(tower_api::models::EventWarning), @@ -592,6 +653,28 @@ impl ResponseEntity for tower_api::apis::default_api::ExportCatalogsSuccess { } } +impl ResponseEntity for tower_api::apis::default_api::ListCatalogsSuccess { + type Data = tower_api::models::ListCatalogsResponse; + + fn extract_data(self) -> Option { + match self { + Self::Status200(data) => Some(data), + Self::UnknownValue(_) => None, + } + } +} + +impl ResponseEntity for tower_api::apis::default_api::DescribeCatalogSuccess { + type Data = tower_api::models::DescribeCatalogResponse; + + fn extract_data(self) -> Option { + match self { + Self::Status200(data) => Some(data), + Self::UnknownValue(_) => None, + } + } +} + impl ResponseEntity for tower_api::apis::default_api::CreateSecretSuccess { type Data = tower_api::models::CreateSecretResponse; @@ -614,6 +697,17 @@ impl ResponseEntity for tower_api::apis::default_api::DescribeSecretsKeySuccess } } +impl ResponseEntity for tower_api::apis::default_api::ListTeamsSuccess { + type Data = tower_api::models::ListTeamsResponse; + + fn extract_data(self) -> Option { + match self { + Self::Status200(data) => Some(data), + Self::UnknownValue(_) => None, + } + } +} + impl ResponseEntity for tower_api::apis::default_api::ListAppsSuccess { type Data = tower_api::models::ListAppsResponse; @@ -843,7 +937,7 @@ pub async fn create_schedule( .map(|(key, value)| RunParameter { name: key, value, - hidden: false, + hidden: None, }) .collect() }); @@ -881,7 +975,7 @@ pub async fn update_schedule( .map(|(key, value)| RunParameter { name: key, value, - hidden: false, + hidden: None, }) .collect() }); diff --git a/crates/tower-cmd/src/apps.rs b/crates/tower-cmd/src/apps.rs index ddb530af..9b90ec35 100644 --- a/crates/tower-cmd/src/apps.rs +++ b/crates/tower-cmd/src/apps.rs @@ -145,7 +145,7 @@ pub async fn do_show(config: Config, cmd: &ArgMatches) { let headers = vec!["#", "Status", "Start Time", "Elapsed Time"] .into_iter() - .map(|h| h.to_string()) + .map(str::to_string) .collect(); let rows = runs @@ -607,7 +607,7 @@ mod tests { #[test] fn test_terminal_statuses_explicit() { - let non_terminal = [Status::Scheduled, Status::Pending, Status::Running]; + let non_terminal = [Status::Scheduled, Status::Pending, Status::Running, Status::Retrying]; for status in non_terminal { let run = Run { status, @@ -638,6 +638,7 @@ mod tests { Status::Scheduled => {} Status::Pending => {} Status::Running => {} + Status::Retrying => {} Status::Crashed => {} Status::Errored => {} Status::Exited => {} @@ -658,6 +659,7 @@ mod tests { let started = [ Status::Running, + Status::Retrying, Status::Crashed, Status::Errored, Status::Exited, diff --git a/crates/tower-cmd/src/catalogs.rs b/crates/tower-cmd/src/catalogs.rs new file mode 100644 index 00000000..5eaedaf0 --- /dev/null +++ b/crates/tower-cmd/src/catalogs.rs @@ -0,0 +1,189 @@ +use clap::{value_parser, Arg, ArgMatches, Command}; +use colored::Colorize; +use config::Config; + +use crate::{api, output, util::cmd}; + +pub fn catalogs_cmd() -> Command { + Command::new("catalogs") + .about("Interact with the catalogs in your Tower account") + .arg_required_else_help(true) + .subcommand( + Command::new("list") + .arg( + Arg::new("environment") + .short('e') + .long("environment") + .default_value("default") + .value_parser(value_parser!(String)) + .help("List catalogs in this environment") + .action(clap::ArgAction::Set), + ) + .arg( + Arg::new("all") + .short('a') + .long("all") + .help("List catalogs across all environments") + .action(clap::ArgAction::SetTrue), + ) + .about("List all of your catalogs"), + ) + .subcommand( + Command::new("show") + .arg( + Arg::new("catalog_name") + .value_parser(value_parser!(String)) + .index(1) + .required(true) + .help("Name of the catalog"), + ) + .arg( + Arg::new("environment") + .short('e') + .long("environment") + .default_value("default") + .value_parser(value_parser!(String)) + .help("Environment the catalog belongs to") + .action(clap::ArgAction::Set), + ) + .about("Show the details of a catalog, including its property names"), + ) +} + +pub async fn do_list(config: Config, args: &ArgMatches) { + let all = cmd::get_bool_flag(args, "all"); + let env = cmd::get_string_flag(args, "environment"); + + let list_response = + output::with_spinner("Listing catalogs", api::list_catalogs(&config, &env, all)).await; + + let headers = vec!["Name", "Type", "Environment"] + .into_iter() + .map(str::to_string) + .collect(); + let data = list_response + .catalogs + .iter() + .map(|catalog| { + vec![ + catalog.name.clone(), + catalog.r#type.clone(), + catalog.environment.clone(), + ] + }) + .collect(); + output::table(headers, data, Some(&list_response.catalogs)); +} + +pub async fn do_show(config: Config, args: &ArgMatches) { + let name = args + .get_one::("catalog_name") + .expect("catalog_name is required"); + let env = cmd::get_string_flag(args, "environment"); + + match api::describe_catalog(&config, name, &env).await { + Ok(response) => { + if output::get_output_mode().is_json() { + output::json(&response); + return; + } + + let catalog = &response.catalog; + + output::detail("Catalog", &catalog.name); + output::detail("Type", &catalog.r#type); + output::detail("Environment", &catalog.environment); + + if !catalog.properties.is_empty() { + output::newline(); + output::header("Properties"); + + let headers = vec!["Name", "Preview"] + .into_iter() + .map(str::to_string) + .collect(); + let data = catalog + .properties + .iter() + .map(|prop| { + vec![ + prop.name.clone(), + prop.preview.dimmed().to_string(), + ] + }) + .collect(); + output::table(headers, data, Some(&response)); + } + } + Err(err) => output::tower_error_and_die(err, "Fetching catalog details failed"), + } +} + +#[cfg(test)] +mod tests { + use super::catalogs_cmd; + + #[test] + fn list_defaults_to_default_environment() { + let matches = catalogs_cmd() + .try_get_matches_from(["catalogs", "list"]) + .expect("list should parse with no args"); + + let (_, list_args) = matches.subcommand().expect("expected list subcommand"); + + assert_eq!(list_args.get_one::("environment").unwrap(), "default"); + assert_eq!(list_args.get_one::("all").copied(), Some(false)); + } + + #[test] + fn list_accepts_environment_flag() { + let matches = catalogs_cmd() + .try_get_matches_from(["catalogs", "list", "-e", "production"]) + .expect("list -e should parse"); + + let (_, list_args) = matches.subcommand().expect("expected list subcommand"); + + assert_eq!(list_args.get_one::("environment").unwrap(), "production"); + } + + #[test] + fn list_accepts_all_flag() { + let matches = catalogs_cmd() + .try_get_matches_from(["catalogs", "list", "--all"]) + .expect("list --all should parse"); + + let (_, list_args) = matches.subcommand().expect("expected list subcommand"); + + assert_eq!(list_args.get_one::("all").copied(), Some(true)); + } + + #[test] + fn show_requires_catalog_name() { + let result = catalogs_cmd().try_get_matches_from(["catalogs", "show"]); + assert!(result.is_err()); + } + + #[test] + fn show_accepts_catalog_name() { + let matches = catalogs_cmd() + .try_get_matches_from(["catalogs", "show", "my-catalog"]) + .expect("show with name should parse"); + + let (_, show_args) = matches.subcommand().expect("expected show subcommand"); + + assert_eq!(show_args.get_one::("catalog_name").unwrap(), "my-catalog"); + assert_eq!(show_args.get_one::("environment").unwrap(), "default"); + } + + #[test] + fn show_accepts_environment_override() { + let matches = catalogs_cmd() + .try_get_matches_from(["catalogs", "show", "my-catalog", "-e", "production"]) + .expect("show with -e should parse"); + + let (_, show_args) = matches.subcommand().expect("expected show subcommand"); + + assert_eq!(show_args.get_one::("catalog_name").unwrap(), "my-catalog"); + assert_eq!(show_args.get_one::("environment").unwrap(), "production"); + } +} diff --git a/crates/tower-cmd/src/environments.rs b/crates/tower-cmd/src/environments.rs index 57609e5f..970677e4 100644 --- a/crates/tower-cmd/src/environments.rs +++ b/crates/tower-cmd/src/environments.rs @@ -1,5 +1,4 @@ use clap::{value_parser, Arg, ArgMatches, Command}; -use colored::Colorize; use config::Config; use crate::{api, output}; @@ -26,10 +25,7 @@ pub fn environments_cmd() -> Command { pub async fn do_list(config: Config) { let resp = output::with_spinner("Listing environments", api::list_environments(&config)).await; - let headers = vec!["Name"] - .into_iter() - .map(|h| h.yellow().to_string()) - .collect(); + let headers = vec!["Name".to_string()]; let envs_data: Vec> = resp .environments diff --git a/crates/tower-cmd/src/lib.rs b/crates/tower-cmd/src/lib.rs index 43de9c31..2d668f5a 100644 --- a/crates/tower-cmd/src/lib.rs +++ b/crates/tower-cmd/src/lib.rs @@ -3,6 +3,7 @@ use config::{Config, Session}; pub mod api; mod apps; +mod catalogs; mod deploy; mod environments; pub mod error; @@ -30,10 +31,12 @@ impl App { pub fn new() -> Self { let cmd = root_cmd(); - // In certain scenarios, we want to load a session from a JWT token supplied as an - // environment variable. This is for programmatic use cases where we want to test the CLI - // in automated environments, for instance. - let session = if let Ok(token) = std::env::var("TOWER_JWT") { + // When TOWER_API_KEY is set, skip session entirely — the API key is self-contained + // and authenticates via X-API-Key header rather than Bearer JWT. + let session = if std::env::var("TOWER_API_KEY").is_ok() { + None + } else if let Ok(token) = std::env::var("TOWER_JWT") { + // Load session from a JWT token for programmatic use cases Session::from_jwt(&token).ok() } else { Session::from_config_dir().ok() @@ -131,6 +134,18 @@ impl App { } } } + Some(("catalogs", sub_matches)) => { + let catalogs_command = sub_matches.subcommand(); + + match catalogs_command { + Some(("list", args)) => catalogs::do_list(sessionized_config, args).await, + Some(("show", args)) => catalogs::do_show(sessionized_config, args).await, + _ => { + catalogs::catalogs_cmd().print_help().unwrap(); + std::process::exit(2); + } + } + } Some(("secrets", sub_matches)) => { let secrets_command = sub_matches.subcommand(); @@ -230,6 +245,7 @@ fn root_cmd() -> Command { .arg_required_else_help(false) .subcommand(session::login_cmd()) .subcommand(apps::apps_cmd()) + .subcommand(catalogs::catalogs_cmd()) .subcommand(schedules::schedules_cmd()) .subcommand(secrets::secrets_cmd()) .subcommand(environments::environments_cmd()) diff --git a/crates/tower-cmd/src/mcp.rs b/crates/tower-cmd/src/mcp.rs index c2c18e47..49dd7beb 100644 --- a/crates/tower-cmd/src/mcp.rs +++ b/crates/tower-cmd/src/mcp.rs @@ -2,7 +2,7 @@ use std::future::Future; use axum::Router; use clap::Command; -use config::{Session, Towerfile}; +use config::{Parameter, Session, Towerfile}; use crypto; use rmcp::{ handler::server::tool::{Parameters, ToolRouter}, @@ -87,8 +87,37 @@ struct AddParameterRequest { #[serde(flatten)] common: CommonParams, name: String, - description: String, - default: String, + /// Description of the parameter. Required for regular parameters, omit for hidden parameters. + description: Option, + /// Default value for the parameter. Mutually exclusive with hidden. + default: Option, + /// Whether the parameter is hidden (value comes from secrets). Mutually exclusive with default. + #[serde(default)] + hidden: bool, +} + +#[derive(Debug, Deserialize, JsonSchema)] +struct EditParameterRequest { + #[serde(flatten)] + common: CommonParams, + /// The name of the existing parameter to edit + name: String, + /// New name for the parameter + new_name: Option, + /// New description for the parameter + description: Option, + /// New default value for the parameter. Mutually exclusive with hidden. + default: Option, + /// Set to true to make hidden, or false to make visible. Mutually exclusive with default. + hidden: Option, +} + +#[derive(Debug, Deserialize, JsonSchema)] +struct RemoveParameterRequest { + #[serde(flatten)] + common: CommonParams, + /// The name of the parameter to remove + name: String, } #[derive(Debug, Deserialize, JsonSchema)] @@ -259,6 +288,10 @@ impl TowerService { Ok(CallToolResult::success(vec![Content::text(message)])) } + fn text_error(message: String) -> Result { + Ok(CallToolResult::error(vec![Content::text(message)])) + } + fn error_result( prefix: &str, error: impl std::fmt::Display + std::fmt::Debug, @@ -269,6 +302,28 @@ impl TowerService { ))])) } + fn modify_towerfile( + common: &CommonParams, + f: impl FnOnce(&mut Towerfile) -> Result, + ) -> Result { + let working_dir = Self::resolve_working_directory(common); + let mut towerfile = match Towerfile::from_dir_str(working_dir.to_str().unwrap()) { + Ok(tf) => tf, + Err(e) => return Self::error_result("Failed to read Towerfile", e), + }; + + let message = match f(&mut towerfile) { + Ok(msg) => msg, + Err(msg) => return Self::text_error(msg), + }; + + let towerfile_path = working_dir.join("Towerfile"); + match towerfile.save(Some(&towerfile_path)) { + Ok(_) => Self::text_success(message), + Err(e) => Self::error_result("Failed to save Towerfile", e), + } + } + fn resolve_working_directory(common: &CommonParams) -> std::path::PathBuf { common .working_directory @@ -279,6 +334,23 @@ impl TowerService { }) } + async fn list_teams_via_api(&self) -> Result { + let response = api::list_teams(&self.config).await.map_err(|e| { + McpError::internal_error( + "Failed to list teams", + Some(json!({"error": e.to_string()})), + ) + })?; + + let teams: Vec = response + .teams + .into_iter() + .map(|team| json!({"name": team.name})) + .collect(); + + Self::json_success(json!({"teams": teams})) + } + fn extract_api_error_message(error: &crate::Error) -> String { let crate::Error::ApiRunError { source } = error else { return error.to_string(); @@ -585,6 +657,10 @@ impl TowerService { #[tool(description = "List teams you belong to")] async fn tower_teams_list(&self) -> Result { + if self.config.api_key.is_some() { + return self.list_teams_via_api().await; + } + let response = api::refresh_session(&self.config).await.map_err(|e| { McpError::internal_error( "Failed to refresh session", @@ -749,59 +825,92 @@ impl TowerService { &self, Parameters(request): Parameters, ) -> Result { - let working_dir = Self::resolve_working_directory(&request.common); - let mut towerfile = match Towerfile::from_dir_str(working_dir.to_str().unwrap()) { - Ok(tf) => tf, - Err(e) => return Self::error_result("Failed to read Towerfile", e), - }; - - if let Some(name) = request.app_name { - towerfile.app.name = name; - } - if let Some(script) = request.script { - towerfile.app.script = script; - } - if let Some(description) = request.description { - towerfile.app.description = Some(description); - } - if let Some(source) = request.source { - towerfile.app.source = source; - } - - let towerfile_path = working_dir.join("Towerfile"); - match towerfile.save(Some(&towerfile_path)) { - Ok(_) => { - Self::text_success(format!("Towerfile updated at {}", towerfile_path.display())) + Self::modify_towerfile(&request.common, |tf| { + if let Some(name) = request.app_name { + tf.app.name = name; } - Err(e) => Self::error_result("Failed to save Towerfile", e), - } + if let Some(script) = request.script { + tf.app.script = script; + } + if let Some(description) = request.description { + tf.app.description = Some(description); + } + if let Some(source) = request.source { + tf.app.source = source; + } + Ok("Towerfile updated".into()) + }) } #[tool( - description = "Add parameter to Towerfile. Use this instead of editing TOML. Optional: working_directory." + description = "Add parameter to Towerfile. For regular params provide description and default. For hidden params set hidden=true (no default). Optional: working_directory." )] async fn tower_file_add_parameter( &self, Parameters(request): Parameters, ) -> Result { - let working_dir = Self::resolve_working_directory(&request.common); - let mut towerfile = match Towerfile::from_dir_str(working_dir.to_str().unwrap()) { - Ok(tf) => tf, - Err(e) => return Self::error_result("Failed to read Towerfile", e), - }; + if request.hidden && request.default.is_some() { + return Self::text_error("hidden and default are mutually exclusive".into()); + } + let name = request.name.clone(); + Self::modify_towerfile(&request.common, |tf| { + tf.set_parameter(&name, Parameter { + name: name.clone(), + description: request.description.unwrap_or_default(), + default: request.default.unwrap_or_default(), + hidden: request.hidden, + }); + Ok(format!("Added parameter '{name}'")) + }) + } - let param_name = request.name.clone(); - towerfile.add_parameter(request.name, request.description, request.default); + #[tool( + description = "Edit an existing parameter in the Towerfile. Provide only the fields to change. hidden and default are mutually exclusive. Optional: working_directory." + )] + async fn tower_file_edit_parameter( + &self, + Parameters(request): Parameters, + ) -> Result { + let name = request.name.clone(); + Self::modify_towerfile(&request.common, |tf| { + let existing = tf.parameters.iter().find(|p| p.name == name) + .ok_or_else(|| format!("Parameter '{name}' not found"))?; + let target_name = request + .new_name + .clone() + .unwrap_or_else(|| existing.name.clone()); + if target_name != name && tf.parameters.iter().any(|p| p.name == target_name) { + return Err(format!("Parameter '{}' already exists", target_name)); + } + let param = Parameter { + name: target_name, + description: request.description.unwrap_or_else(|| existing.description.clone()), + default: request.default.unwrap_or_else(|| existing.default.clone()), + hidden: request.hidden.unwrap_or(existing.hidden), + }; + if param.hidden && !param.default.is_empty() { + return Err("hidden and default are mutually exclusive".into()); + } + tf.set_parameter(&name, param); + Ok(format!("Updated parameter '{name}'")) + }) + } - let towerfile_path = working_dir.join("Towerfile"); - match towerfile.save(Some(&towerfile_path)) { - Ok(_) => Self::text_success(format!( - "Added parameter '{}' to {}", - param_name, - towerfile_path.display() - )), - Err(e) => Self::error_result("Failed to save Towerfile", e), - } + #[tool( + description = "Remove a parameter from the Towerfile. Optional: working_directory." + )] + async fn tower_file_remove_parameter( + &self, + Parameters(request): Parameters, + ) -> Result { + let name = request.name.clone(); + Self::modify_towerfile(&request.common, |tf| { + if tf.remove_parameter(&name) { + Ok(format!("Removed parameter '{name}'")) + } else { + Err(format!("Parameter '{name}' not found")) + } + }) } #[tool(description = "Validate Towerfile configuration. Optional: working_directory.")] @@ -870,8 +979,8 @@ All tools accept optional working_directory parameter to specify which project t Skip this step if project with pyproject.toml already exists 1. TOWERFILE (required for all Tower operations): - tower_file_generate → tower_file_update → tower_file_add_parameter → tower_file_validate - CRITICAL: Always use tower_file_update or tower_file_add_parameter to modify + tower_file_generate → tower_file_update → tower_file_add/edit/remove_parameter → tower_file_validate + CRITICAL: Always use tower_file_update or tower_file_add/edit/remove_parameter to modify NEVER edit Towerfile TOML directly 2. LOCAL DEVELOPMENT (preferred during development): @@ -923,7 +1032,7 @@ IMPORTANT REMINDERS: .map(|mut schedule| { if let Some(parameters) = schedule.parameters.as_mut() { for parameter in parameters { - if parameter.hidden { + if parameter.hidden.unwrap_or(false) { parameter.value = "[hidden]".to_string(); } } @@ -1008,7 +1117,7 @@ impl ServerHandler for TowerService { Rules: - MCP tools are the authoritative Tower interface (not wrappers) -- Use tower_file_update/add_parameter to modify Towerfiles (never edit TOML directly) +- Use tower_file_update/add/edit/remove_parameter to modify Towerfiles (never edit TOML directly) - DO NOT add hatchling/setuptools to pyproject.toml - Tower handles deployment - Tower apps need: pyproject.toml (deps only), Python code, Towerfile - Pass run parameters as a JSON object {\"key\": \"value\"}, not as CLI flags diff --git a/crates/tower-cmd/src/output.rs b/crates/tower-cmd/src/output.rs index 36eace9b..eb324ba6 100644 --- a/crates/tower-cmd/src/output.rs +++ b/crates/tower-cmd/src/output.rs @@ -203,8 +203,9 @@ pub fn paragraph(msg: &str) -> String { pub fn config_error(err: config::Error) { let msg = match err { - config::Error::ConfigDirNotFound => "No home directory found".to_string(), + config::Error::ConfigDirNotFound => "Config directory not found".to_string(), config::Error::NoHomeDir => "No home directory found".to_string(), + config::Error::Io { ref source } => format!("IO error: {}", source), config::Error::NoSession => "No session".to_string(), config::Error::InvalidTowerfile => { "Couldn't read the Towerfile in this directory".to_string() @@ -457,7 +458,7 @@ pub fn table(headers: Vec, data: Vec>, json_da .table() .border(Border::builder().build()) .separator(separator) - .title(headers.iter().map(|h| h.yellow().to_string())); + .title(headers.iter().map(|h| h.bold().yellow().to_string())); if let Err(err) = print_stdout(table) { if err.kind() == io::ErrorKind::BrokenPipe { diff --git a/crates/tower-cmd/src/run.rs b/crates/tower-cmd/src/run.rs index 631fa6eb..6bf2f7cd 100644 --- a/crates/tower-cmd/src/run.rs +++ b/crates/tower-cmd/src/run.rs @@ -254,6 +254,16 @@ where output::error(&format!("Your local run crashed with exit code: {}", code)); return Err(Error::AppCrashed); } + Status::Failed { + error_code, + error_message, + } => { + output::error(&format!( + "Your local run failed due to a platform error (code: {}, message: {})", + error_code, error_message + )); + return Err(Error::AppCrashed); + } _ => { debug!("Unexpected status after monitoring: {:?}", status_result); output::error("An unexpected error occurred while monitoring your local run status!"); @@ -703,6 +713,10 @@ async fn monitor_cli_status( debug!("Run crashed, stopping status monitoring"); return status; } + Status::Failed { .. } => { + debug!("Run failed at platform layer, stopping status monitoring"); + return status; + } _ => { debug!("Handle status: other, continuing to monitor"); sleep(Duration::from_millis(100)).await; diff --git a/crates/tower-cmd/src/schedules.rs b/crates/tower-cmd/src/schedules.rs index bfdd4d13..59562cf2 100644 --- a/crates/tower-cmd/src/schedules.rs +++ b/crates/tower-cmd/src/schedules.rs @@ -125,13 +125,10 @@ pub async fn do_list(config: Config, args: &ArgMatches) { return; } - let headers = vec![ - "ID".yellow().to_string(), - "App".yellow().to_string(), - "Environment".yellow().to_string(), - "Cron".yellow().to_string(), - "Status".yellow().to_string(), - ]; + let headers = vec!["ID", "App", "Environment", "Cron", "Status"] + .into_iter() + .map(str::to_string) + .collect(); let rows: Vec> = response .schedules diff --git a/crates/tower-cmd/src/secrets.rs b/crates/tower-cmd/src/secrets.rs index 71198856..53c63596 100644 --- a/crates/tower-cmd/src/secrets.rs +++ b/crates/tower-cmd/src/secrets.rs @@ -112,11 +112,10 @@ pub async fn do_list(config: Config, args: &ArgMatches) { ) .await; - let headers = vec![ - "Secret".bold().yellow().to_string(), - "Environment".bold().yellow().to_string(), - "Value".bold().yellow().to_string(), - ]; + let headers = vec!["Secret", "Environment", "Value"] + .into_iter() + .map(str::to_string) + .collect(); let data = list_response .secrets .iter() @@ -137,11 +136,10 @@ pub async fn do_list(config: Config, args: &ArgMatches) { let list_response = output::with_spinner("Listing secrets", api::list_secrets(&config, &env, all)).await; - let headers = vec![ - "Secret".bold().yellow().to_string(), - "Environment".bold().yellow().to_string(), - "Preview".bold().yellow().to_string(), - ]; + let headers = vec!["Secret", "Environment", "Preview"] + .into_iter() + .map(str::to_string) + .collect(); let data = list_response .secrets .iter() diff --git a/crates/tower-cmd/src/session.rs b/crates/tower-cmd/src/session.rs index 8f0f8f24..65a6967a 100644 --- a/crates/tower-cmd/src/session.rs +++ b/crates/tower-cmd/src/session.rs @@ -1,5 +1,6 @@ use crate::output; use clap::{Arg, ArgMatches, Command}; +use colored::Colorize; use config::{Config, Session}; use tokio::{time, time::Duration}; use tower_api::models::CreateDeviceLoginTicketResponse; @@ -22,6 +23,22 @@ pub fn login_cmd() -> Command { pub async fn do_login(config: Config, args: &ArgMatches) { output::banner(); + if std::env::var("TOWER_API_KEY").is_ok() { + output::write(&format!( + "{} TOWER_API_KEY is set. As long as this environment variable is present, \ + the CLI will authenticate using the API key and ignore the session \ + created by this login flow.\n", + "Warning:".yellow(), + )); + + eprint!("Do you want to continue? [y/N] "); + let mut input = String::new(); + if std::io::stdin().read_line(&mut input).is_err() || !input.trim().eq_ignore_ascii_case("y") + { + return; + } + } + // Open a browser by default, unless the --no-browser flag is set. let open_browser = !args.get_flag("no-browser"); diff --git a/crates/tower-cmd/src/teams.rs b/crates/tower-cmd/src/teams.rs index 1a5a9174..d0cc2413 100644 --- a/crates/tower-cmd/src/teams.rs +++ b/crates/tower-cmd/src/teams.rs @@ -48,18 +48,39 @@ async fn refresh_session(config: &Config) -> config::Session { } pub async fn do_list(config: Config) { + if config.api_key.is_some() { + do_list_via_api(&config).await; + } else { + do_list_via_session(&config).await; + } +} + +async fn do_list_via_api(config: &Config) { + let resp = output::with_spinner("Fetching teams", api::list_teams(config)).await; + + let headers = vec!["Name".to_string()]; + + let teams_data: Vec> = resp + .teams + .iter() + .map(|team| vec![team.name.clone()]) + .collect(); + + output::newline(); + output::table(headers, teams_data, None::<&Vec>); + output::newline(); +} + +async fn do_list_via_session(config: &Config) { // Refresh the session and get the updated data - let session = refresh_session(&config).await; + let session = refresh_session(config).await; // Get the current active team from the session let active_team = session.active_team.clone(); let active_team_name = active_team.map(|team| team.name.clone()); // Create headers for the table - let headers = vec!["", "Name"] - .into_iter() - .map(|h| h.yellow().to_string()) - .collect(); + let headers = vec!["".to_string(), "Name".to_string()]; // Format the teams data for the table let teams = session.teams.clone(); diff --git a/crates/tower-runtime/src/auto_cleanup.rs b/crates/tower-runtime/src/auto_cleanup.rs index 992fb23f..9e892d55 100644 --- a/crates/tower-runtime/src/auto_cleanup.rs +++ b/crates/tower-runtime/src/auto_cleanup.rs @@ -113,7 +113,7 @@ mod tests { } async fn status(&self) -> Result { - Ok(*self.status.lock().await) + Ok(self.status.lock().await.clone()) } } diff --git a/crates/tower-runtime/src/lib.rs b/crates/tower-runtime/src/lib.rs index b4f56591..6ebbb061 100644 --- a/crates/tower-runtime/src/lib.rs +++ b/crates/tower-runtime/src/lib.rs @@ -37,18 +37,26 @@ pub struct Output { pub line: String, } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub enum Status { None, Running, Exited, - Crashed { code: i32 }, + Crashed { + code: i32, + }, + /// A platform-level failure (not the user's app). For example, pod scheduling + /// failures, image pull errors, or other infrastructure issues. + Failed { + error_code: String, + error_message: String, + }, } impl Status { /// Returns true if this status represents a terminal state (run is finished) pub fn is_terminal(&self) -> bool { - matches!(self, Status::Exited | Status::Crashed { .. }) + matches!(self, Status::Exited | Status::Crashed { .. } | Status::Failed { .. }) } } diff --git a/crates/tower-runtime/src/local.rs b/crates/tower-runtime/src/local.rs index ec2ea64f..707d4dbb 100644 --- a/crates/tower-runtime/src/local.rs +++ b/crates/tower-runtime/src/local.rs @@ -368,7 +368,7 @@ impl App for LocalApp { async fn status(&self) -> Result { let mut status = self.status.lock().await; - if let Some(status) = *status { + if let Some(status) = status.clone() { Ok(status) } else { let mut waiter = self.waiter.lock().await; @@ -384,7 +384,7 @@ impl App for LocalApp { Ok(Status::Exited) } else { let next_status = Status::Crashed { code: t }; - *status = Some(next_status); + *status = Some(next_status.clone()); Ok(next_status) } } diff --git a/crates/tower-runtime/tests/local_test.rs b/crates/tower-runtime/tests/local_test.rs index 2a0c741f..5dda4d9d 100644 --- a/crates/tower-runtime/tests/local_test.rs +++ b/crates/tower-runtime/tests/local_test.rs @@ -373,5 +373,8 @@ async fn test_abort_on_dependency_installation_failure() { Status::None => { panic!("App should have a status"); } + Status::Failed { .. } => { + panic!("App should have crashed, not failed with a platform error"); + } } } diff --git a/crates/tower-telemetry/src/logging.rs b/crates/tower-telemetry/src/logging.rs index 03e8e80e..021e9cb9 100644 --- a/crates/tower-telemetry/src/logging.rs +++ b/crates/tower-telemetry/src/logging.rs @@ -135,6 +135,7 @@ macro_rules! error { } /// LogLevel describes the various log levels that can be used in the application. +#[derive(PartialEq, PartialOrd)] pub enum LogLevel { Debug, Info, @@ -178,8 +179,9 @@ fn should_use_color(destination: &LogDestination) -> bool { } } -fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtLayer { +fn create_fmt_layer(level: &LogLevel, format: LogFormat, destination: LogDestination) -> BoxedFmtLayer { let use_color = should_use_color(&destination); + let with_target = *level < LogLevel::Warn; match destination { LogDestination::Stdout => match format { @@ -187,7 +189,7 @@ fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtL fmt::layer().event_format( fmt::format() .pretty() - .with_target(false) + .with_target(with_target) .with_file(false) .with_line_number(false) .with_ansi(use_color), @@ -197,7 +199,7 @@ fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtL fmt::layer().event_format( fmt::format() .json() - .with_target(false) + .with_target(with_target) .with_file(false) .with_line_number(false) .with_ansi(use_color), @@ -212,7 +214,7 @@ fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtL .event_format( fmt::format() .pretty() - .with_target(false) + .with_target(with_target) .with_file(false) .with_line_number(false) .with_ansi(use_color), @@ -224,7 +226,7 @@ fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtL .event_format( fmt::format() .json() - .with_target(false) + .with_target(with_target) .with_file(false) .with_line_number(false) .with_ansi(use_color), @@ -237,13 +239,13 @@ fn create_fmt_layer(format: LogFormat, destination: LogDestination) -> BoxedFmtL } pub fn enable_logging(level: LogLevel, format: LogFormat, destination: LogDestination) { - let filter = EnvFilter::new(level) + let filter = EnvFilter::new(&level) .add_directive("h2=off".parse().unwrap()) .add_directive("tower::buffer=off".parse().unwrap()) .add_directive("hyper_util=off".parse().unwrap()); let subscriber = tracing_subscriber::registry() - .with(create_fmt_layer(format, destination)) + .with(create_fmt_layer(&level, format, destination)) .with(filter); let _ = tracing::subscriber::set_global_default(subscriber); diff --git a/pyproject.toml b/pyproject.toml index cca6b3fb..581915ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "tower" -version = "0.3.55" +version = "0.3.56" description = "Tower CLI and runtime environment for Tower." authors = [{ name = "Tower Computing Inc.", email = "brad@tower.dev" }] readme = "README.md" diff --git a/src/tower/tower_api_client/api/default/create_guest.py b/src/tower/tower_api_client/api/default/create_guest.py new file mode 100644 index 00000000..31e8fa61 --- /dev/null +++ b/src/tower/tower_api_client/api/default/create_guest.py @@ -0,0 +1,171 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.create_guest_params import CreateGuestParams +from ...models.create_guest_response import CreateGuestResponse +from ...models.error_model import ErrorModel +from ...types import Response + + +def _get_kwargs( + *, + body: CreateGuestParams, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/guests", + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> CreateGuestResponse | ErrorModel: + if response.status_code == 200: + response_200 = CreateGuestResponse.from_dict(response.json()) + + return response_200 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[CreateGuestResponse | ErrorModel]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, + body: CreateGuestParams, +) -> Response[CreateGuestResponse | ErrorModel]: + """Create guest + + Creates a new guest with access to a specific externally accessible app and returns a login URL to + share with them. + + Args: + body (CreateGuestParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CreateGuestResponse | ErrorModel] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient, + body: CreateGuestParams, +) -> CreateGuestResponse | ErrorModel | None: + """Create guest + + Creates a new guest with access to a specific externally accessible app and returns a login URL to + share with them. + + Args: + body (CreateGuestParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CreateGuestResponse | ErrorModel + """ + + return sync_detailed( + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient, + body: CreateGuestParams, +) -> Response[CreateGuestResponse | ErrorModel]: + """Create guest + + Creates a new guest with access to a specific externally accessible app and returns a login URL to + share with them. + + Args: + body (CreateGuestParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[CreateGuestResponse | ErrorModel] + """ + + kwargs = _get_kwargs( + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient, + body: CreateGuestParams, +) -> CreateGuestResponse | ErrorModel | None: + """Create guest + + Creates a new guest with access to a specific externally accessible app and returns a login URL to + share with them. + + Args: + body (CreateGuestParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + CreateGuestResponse | ErrorModel + """ + + return ( + await asyncio_detailed( + client=client, + body=body, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/delete_guest.py b/src/tower/tower_api_client/api/default/delete_guest.py new file mode 100644 index 00000000..36ae7014 --- /dev/null +++ b/src/tower/tower_api_client/api/default/delete_guest.py @@ -0,0 +1,161 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.delete_guest_output_body import DeleteGuestOutputBody +from ...models.error_model import ErrorModel +from ...types import Response + + +def _get_kwargs( + guest_id: str, +) -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "delete", + "url": "/guests/{guest_id}".format( + guest_id=quote(str(guest_id), safe=""), + ), + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> DeleteGuestOutputBody | ErrorModel: + if response.status_code == 204: + response_204 = DeleteGuestOutputBody.from_dict(response.json()) + + return response_204 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[DeleteGuestOutputBody | ErrorModel]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + guest_id: str, + *, + client: AuthenticatedClient, +) -> Response[DeleteGuestOutputBody | ErrorModel]: + """Delete guest + + Deletes a guest and revokes their access. Any active sessions will be invalidated. + + Args: + guest_id (str): The ID of the guest to delete. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[DeleteGuestOutputBody | ErrorModel] + """ + + kwargs = _get_kwargs( + guest_id=guest_id, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + guest_id: str, + *, + client: AuthenticatedClient, +) -> DeleteGuestOutputBody | ErrorModel | None: + """Delete guest + + Deletes a guest and revokes their access. Any active sessions will be invalidated. + + Args: + guest_id (str): The ID of the guest to delete. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + DeleteGuestOutputBody | ErrorModel + """ + + return sync_detailed( + guest_id=guest_id, + client=client, + ).parsed + + +async def asyncio_detailed( + guest_id: str, + *, + client: AuthenticatedClient, +) -> Response[DeleteGuestOutputBody | ErrorModel]: + """Delete guest + + Deletes a guest and revokes their access. Any active sessions will be invalidated. + + Args: + guest_id (str): The ID of the guest to delete. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[DeleteGuestOutputBody | ErrorModel] + """ + + kwargs = _get_kwargs( + guest_id=guest_id, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + guest_id: str, + *, + client: AuthenticatedClient, +) -> DeleteGuestOutputBody | ErrorModel | None: + """Delete guest + + Deletes a guest and revokes their access. Any active sessions will be invalidated. + + Args: + guest_id (str): The ID of the guest to delete. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + DeleteGuestOutputBody | ErrorModel + """ + + return ( + await asyncio_detailed( + guest_id=guest_id, + client=client, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/describe_catalog.py b/src/tower/tower_api_client/api/default/describe_catalog.py new file mode 100644 index 00000000..9f990bb3 --- /dev/null +++ b/src/tower/tower_api_client/api/default/describe_catalog.py @@ -0,0 +1,182 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.describe_catalog_response import DescribeCatalogResponse +from ...models.error_model import ErrorModel +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + name: str, + *, + environment: str | Unset = "default", +) -> dict[str, Any]: + params: dict[str, Any] = {} + + params["environment"] = environment + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/catalogs/{name}".format( + name=quote(str(name), safe=""), + ), + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> DescribeCatalogResponse | ErrorModel: + if response.status_code == 200: + response_200 = DescribeCatalogResponse.from_dict(response.json()) + + return response_200 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[DescribeCatalogResponse | ErrorModel]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + name: str, + *, + client: AuthenticatedClient, + environment: str | Unset = "default", +) -> Response[DescribeCatalogResponse | ErrorModel]: + """Describe catalog + + Returns details for a specific catalog, including its property names and previews. + + Args: + name (str): The name of the catalog. + environment (str | Unset): The environment of the catalog. Default: 'default'. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[DescribeCatalogResponse | ErrorModel] + """ + + kwargs = _get_kwargs( + name=name, + environment=environment, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + name: str, + *, + client: AuthenticatedClient, + environment: str | Unset = "default", +) -> DescribeCatalogResponse | ErrorModel | None: + """Describe catalog + + Returns details for a specific catalog, including its property names and previews. + + Args: + name (str): The name of the catalog. + environment (str | Unset): The environment of the catalog. Default: 'default'. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + DescribeCatalogResponse | ErrorModel + """ + + return sync_detailed( + name=name, + client=client, + environment=environment, + ).parsed + + +async def asyncio_detailed( + name: str, + *, + client: AuthenticatedClient, + environment: str | Unset = "default", +) -> Response[DescribeCatalogResponse | ErrorModel]: + """Describe catalog + + Returns details for a specific catalog, including its property names and previews. + + Args: + name (str): The name of the catalog. + environment (str | Unset): The environment of the catalog. Default: 'default'. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[DescribeCatalogResponse | ErrorModel] + """ + + kwargs = _get_kwargs( + name=name, + environment=environment, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + name: str, + *, + client: AuthenticatedClient, + environment: str | Unset = "default", +) -> DescribeCatalogResponse | ErrorModel | None: + """Describe catalog + + Returns details for a specific catalog, including its property names and previews. + + Args: + name (str): The name of the catalog. + environment (str | Unset): The environment of the catalog. Default: 'default'. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + DescribeCatalogResponse | ErrorModel + """ + + return ( + await asyncio_detailed( + name=name, + client=client, + environment=environment, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/describe_organization_usage.py b/src/tower/tower_api_client/api/default/describe_organization_usage.py new file mode 100644 index 00000000..9cfc44c2 --- /dev/null +++ b/src/tower/tower_api_client/api/default/describe_organization_usage.py @@ -0,0 +1,134 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_model import ErrorModel +from ...models.organization_usage import OrganizationUsage +from ...types import Response + + +def _get_kwargs() -> dict[str, Any]: + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/usage", + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorModel | OrganizationUsage: + if response.status_code == 200: + response_200 = OrganizationUsage.from_dict(response.json()) + + return response_200 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorModel | OrganizationUsage]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, +) -> Response[ErrorModel | OrganizationUsage]: + """Describe organization usage + + Describe usage statistics for the user's organization. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | OrganizationUsage] + """ + + kwargs = _get_kwargs() + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient, +) -> ErrorModel | OrganizationUsage | None: + """Describe organization usage + + Describe usage statistics for the user's organization. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | OrganizationUsage + """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient, +) -> Response[ErrorModel | OrganizationUsage]: + """Describe organization usage + + Describe usage statistics for the user's organization. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | OrganizationUsage] + """ + + kwargs = _get_kwargs() + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient, +) -> ErrorModel | OrganizationUsage | None: + """Describe organization usage + + Describe usage statistics for the user's organization. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | OrganizationUsage + """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/leave_team.py b/src/tower/tower_api_client/api/default/leave_team.py index fabc26c3..b9fc369c 100644 --- a/src/tower/tower_api_client/api/default/leave_team.py +++ b/src/tower/tower_api_client/api/default/leave_team.py @@ -54,8 +54,8 @@ def sync_detailed( ) -> Response[ErrorModel | LeaveTeamResponse]: """Leave team - Remove yourself from a team, if that's something you'd like to do for whatever reason. If you're the - last member of a team, you cannot remove yourself. You should delete the team instead. + Remove yourself from a team. If you're the last member of a team, you cannot remove yourself. You + should delete the team instead. Args: name (str): The name of the team to leave @@ -86,8 +86,8 @@ def sync( ) -> ErrorModel | LeaveTeamResponse | None: """Leave team - Remove yourself from a team, if that's something you'd like to do for whatever reason. If you're the - last member of a team, you cannot remove yourself. You should delete the team instead. + Remove yourself from a team. If you're the last member of a team, you cannot remove yourself. You + should delete the team instead. Args: name (str): The name of the team to leave @@ -113,8 +113,8 @@ async def asyncio_detailed( ) -> Response[ErrorModel | LeaveTeamResponse]: """Leave team - Remove yourself from a team, if that's something you'd like to do for whatever reason. If you're the - last member of a team, you cannot remove yourself. You should delete the team instead. + Remove yourself from a team. If you're the last member of a team, you cannot remove yourself. You + should delete the team instead. Args: name (str): The name of the team to leave @@ -143,8 +143,8 @@ async def asyncio( ) -> ErrorModel | LeaveTeamResponse | None: """Leave team - Remove yourself from a team, if that's something you'd like to do for whatever reason. If you're the - last member of a team, you cannot remove yourself. You should delete the team instead. + Remove yourself from a team. If you're the last member of a team, you cannot remove yourself. You + should delete the team instead. Args: name (str): The name of the team to leave diff --git a/src/tower/tower_api_client/api/default/list_guests.py b/src/tower/tower_api_client/api/default/list_guests.py new file mode 100644 index 00000000..117a77b8 --- /dev/null +++ b/src/tower/tower_api_client/api/default/list_guests.py @@ -0,0 +1,166 @@ +from http import HTTPStatus +from typing import Any + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_model import ErrorModel +from ...models.list_guests_response import ListGuestsResponse +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + app: str | Unset = UNSET, +) -> dict[str, Any]: + params: dict[str, Any] = {} + + params["app"] = app + + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} + + _kwargs: dict[str, Any] = { + "method": "get", + "url": "/guests", + "params": params, + } + + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorModel | ListGuestsResponse: + if response.status_code == 200: + response_200 = ListGuestsResponse.from_dict(response.json()) + + return response_200 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorModel | ListGuestsResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + *, + client: AuthenticatedClient, + app: str | Unset = UNSET, +) -> Response[ErrorModel | ListGuestsResponse]: + """List guests + + Lists all guests for the current account, optionally filtered by app. + + Args: + app (str | Unset): Filter guests by app name. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | ListGuestsResponse] + """ + + kwargs = _get_kwargs( + app=app, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + *, + client: AuthenticatedClient, + app: str | Unset = UNSET, +) -> ErrorModel | ListGuestsResponse | None: + """List guests + + Lists all guests for the current account, optionally filtered by app. + + Args: + app (str | Unset): Filter guests by app name. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | ListGuestsResponse + """ + + return sync_detailed( + client=client, + app=app, + ).parsed + + +async def asyncio_detailed( + *, + client: AuthenticatedClient, + app: str | Unset = UNSET, +) -> Response[ErrorModel | ListGuestsResponse]: + """List guests + + Lists all guests for the current account, optionally filtered by app. + + Args: + app (str | Unset): Filter guests by app name. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | ListGuestsResponse] + """ + + kwargs = _get_kwargs( + app=app, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + *, + client: AuthenticatedClient, + app: str | Unset = UNSET, +) -> ErrorModel | ListGuestsResponse | None: + """List guests + + Lists all guests for the current account, optionally filtered by app. + + Args: + app (str | Unset): Filter guests by app name. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | ListGuestsResponse + """ + + return ( + await asyncio_detailed( + client=client, + app=app, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/list_teams.py b/src/tower/tower_api_client/api/default/list_teams.py index 8706f512..c298077b 100644 --- a/src/tower/tower_api_client/api/default/list_teams.py +++ b/src/tower/tower_api_client/api/default/list_teams.py @@ -63,7 +63,7 @@ def sync_detailed( ) -> Response[ErrorModel | ListTeamsResponse]: """List teams - List all the teams that the user is a member of. + List all the teams that you are a member of. Args: page (int | Unset): The page number to fetch. Default: 1. @@ -97,7 +97,7 @@ def sync( ) -> ErrorModel | ListTeamsResponse | None: """List teams - List all the teams that the user is a member of. + List all the teams that you are a member of. Args: page (int | Unset): The page number to fetch. Default: 1. @@ -126,7 +126,7 @@ async def asyncio_detailed( ) -> Response[ErrorModel | ListTeamsResponse]: """List teams - List all the teams that the user is a member of. + List all the teams that you are a member of. Args: page (int | Unset): The page number to fetch. Default: 1. @@ -158,7 +158,7 @@ async def asyncio( ) -> ErrorModel | ListTeamsResponse | None: """List teams - List all the teams that the user is a member of. + List all the teams that you are a member of. Args: page (int | Unset): The page number to fetch. Default: 1. diff --git a/src/tower/tower_api_client/api/default/regenerate_guest_login_url.py b/src/tower/tower_api_client/api/default/regenerate_guest_login_url.py new file mode 100644 index 00000000..0937e249 --- /dev/null +++ b/src/tower/tower_api_client/api/default/regenerate_guest_login_url.py @@ -0,0 +1,189 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ...client import AuthenticatedClient, Client +from ...models.error_model import ErrorModel +from ...models.regenerate_guest_login_url_params import RegenerateGuestLoginURLParams +from ...models.regenerate_guest_login_url_response import ( + RegenerateGuestLoginURLResponse, +) +from ...types import Response + + +def _get_kwargs( + guest_id: str, + *, + body: RegenerateGuestLoginURLParams, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/guests/{guest_id}/login-url".format( + guest_id=quote(str(guest_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorModel | RegenerateGuestLoginURLResponse: + if response.status_code == 200: + response_200 = RegenerateGuestLoginURLResponse.from_dict(response.json()) + + return response_200 + + response_default = ErrorModel.from_dict(response.json()) + + return response_default + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorModel | RegenerateGuestLoginURLResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + guest_id: str, + *, + client: AuthenticatedClient, + body: RegenerateGuestLoginURLParams, +) -> Response[ErrorModel | RegenerateGuestLoginURLResponse]: + """Regenerate guest login URL + + Creates a new login URL for an existing guest. Use this if the previous URL expired or was + compromised. + + Args: + guest_id (str): The ID of the guest to regenerate the login URL for. + body (RegenerateGuestLoginURLParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | RegenerateGuestLoginURLResponse] + """ + + kwargs = _get_kwargs( + guest_id=guest_id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + guest_id: str, + *, + client: AuthenticatedClient, + body: RegenerateGuestLoginURLParams, +) -> ErrorModel | RegenerateGuestLoginURLResponse | None: + """Regenerate guest login URL + + Creates a new login URL for an existing guest. Use this if the previous URL expired or was + compromised. + + Args: + guest_id (str): The ID of the guest to regenerate the login URL for. + body (RegenerateGuestLoginURLParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | RegenerateGuestLoginURLResponse + """ + + return sync_detailed( + guest_id=guest_id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + guest_id: str, + *, + client: AuthenticatedClient, + body: RegenerateGuestLoginURLParams, +) -> Response[ErrorModel | RegenerateGuestLoginURLResponse]: + """Regenerate guest login URL + + Creates a new login URL for an existing guest. Use this if the previous URL expired or was + compromised. + + Args: + guest_id (str): The ID of the guest to regenerate the login URL for. + body (RegenerateGuestLoginURLParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorModel | RegenerateGuestLoginURLResponse] + """ + + kwargs = _get_kwargs( + guest_id=guest_id, + body=body, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + guest_id: str, + *, + client: AuthenticatedClient, + body: RegenerateGuestLoginURLParams, +) -> ErrorModel | RegenerateGuestLoginURLResponse | None: + """Regenerate guest login URL + + Creates a new login URL for an existing guest. Use this if the previous URL expired or was + compromised. + + Args: + guest_id (str): The ID of the guest to regenerate the login URL for. + body (RegenerateGuestLoginURLParams): + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorModel | RegenerateGuestLoginURLResponse + """ + + return ( + await asyncio_detailed( + guest_id=guest_id, + client=client, + body=body, + ) + ).parsed diff --git a/src/tower/tower_api_client/api/default/update_organization.py b/src/tower/tower_api_client/api/default/update_organization.py index 65f48c39..614eee9b 100644 --- a/src/tower/tower_api_client/api/default/update_organization.py +++ b/src/tower/tower_api_client/api/default/update_organization.py @@ -4,6 +4,7 @@ import httpx +from ... import errors from ...client import AuthenticatedClient, Client from ...models.error_model import ErrorModel from ...models.update_organization_params import UpdateOrganizationParams @@ -35,15 +36,41 @@ def _get_kwargs( def _parse_response( *, client: AuthenticatedClient | Client, response: httpx.Response -) -> ErrorModel | UpdateOrganizationResponse: +) -> ErrorModel | UpdateOrganizationResponse | None: if response.status_code == 200: response_200 = UpdateOrganizationResponse.from_dict(response.json()) return response_200 - response_default = ErrorModel.from_dict(response.json()) + if response.status_code == 403: + response_403 = ErrorModel.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorModel.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorModel.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorModel.from_dict(response.json()) + + return response_422 + + if response.status_code == 500: + response_500 = ErrorModel.from_dict(response.json()) + + return response_500 - return response_default + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None def _build_response( diff --git a/src/tower/tower_api_client/models/__init__.py b/src/tower/tower_api_client/models/__init__.py index 0106e7c9..ae9cfab0 100644 --- a/src/tower/tower_api_client/models/__init__.py +++ b/src/tower/tower_api_client/models/__init__.py @@ -34,6 +34,8 @@ from .create_device_login_ticket_response import CreateDeviceLoginTicketResponse from .create_environment_params import CreateEnvironmentParams from .create_environment_response import CreateEnvironmentResponse +from .create_guest_params import CreateGuestParams +from .create_guest_response import CreateGuestResponse from .create_password_reset_params import CreatePasswordResetParams from .create_password_reset_response import CreatePasswordResetResponse from .create_sandbox_secrets_params import CreateSandboxSecretsParams @@ -56,6 +58,7 @@ from .delete_authenticator_params import DeleteAuthenticatorParams from .delete_authenticator_response import DeleteAuthenticatorResponse from .delete_catalog_response import DeleteCatalogResponse +from .delete_guest_output_body import DeleteGuestOutputBody from .delete_schedule_params import DeleteScheduleParams from .delete_schedule_response import DeleteScheduleResponse from .delete_secret_response import DeleteSecretResponse @@ -72,6 +75,7 @@ from .describe_app_response import DescribeAppResponse from .describe_app_version_response import DescribeAppVersionResponse from .describe_authentication_context_body import DescribeAuthenticationContextBody +from .describe_catalog_response import DescribeCatalogResponse from .describe_device_login_session_response import DescribeDeviceLoginSessionResponse from .describe_email_preferences_body import DescribeEmailPreferencesBody from .describe_plan_response import DescribePlanResponse @@ -106,7 +110,9 @@ from .get_feature_flag_response_body_value_type import ( GetFeatureFlagResponseBodyValueType, ) +from .guest import Guest from .invite_team_member_params import InviteTeamMemberParams +from .invite_team_member_params_role import InviteTeamMemberParamsRole from .invite_team_member_response import InviteTeamMemberResponse from .leave_team_response import LeaveTeamResponse from .list_alerts_response import ListAlertsResponse @@ -119,6 +125,7 @@ from .list_authenticators_response import ListAuthenticatorsResponse from .list_catalogs_response import ListCatalogsResponse from .list_environments_response import ListEnvironmentsResponse +from .list_guests_response import ListGuestsResponse from .list_my_team_invitations_response import ListMyTeamInvitationsResponse from .list_runners_response import ListRunnersResponse from .list_runs_response import ListRunsResponse @@ -131,11 +138,14 @@ from .list_teams_response import ListTeamsResponse from .list_webhooks_response import ListWebhooksResponse from .organization import Organization +from .organization_usage import OrganizationUsage from .pagination import Pagination from .parameter import Parameter from .plan import Plan from .refresh_session_params import RefreshSessionParams from .refresh_session_response import RefreshSessionResponse +from .regenerate_guest_login_url_params import RegenerateGuestLoginURLParams +from .regenerate_guest_login_url_response import RegenerateGuestLoginURLResponse from .remove_team_member_params import RemoveTeamMemberParams from .remove_team_member_response import RemoveTeamMemberResponse from .resend_team_invitation_params import ResendTeamInvitationParams @@ -146,6 +156,7 @@ from .run_app_params import RunAppParams from .run_app_params_parameters import RunAppParamsParameters from .run_app_response import RunAppResponse +from .run_attempt import RunAttempt from .run_failure_alert import RunFailureAlert from .run_graph_node import RunGraphNode from .run_graph_run_id import RunGraphRunID @@ -154,6 +165,7 @@ from .run_log_line_channel import RunLogLineChannel from .run_parameter import RunParameter from .run_results import RunResults +from .run_retry_policy import RunRetryPolicy from .run_run_initiator_details import RunRunInitiatorDetails from .run_statistics import RunStatistics from .run_status import RunStatus @@ -188,6 +200,7 @@ from .token import Token from .unverified_authenticator import UnverifiedAuthenticator from .update_account_params import UpdateAccountParams +from .update_account_params_execution_region import UpdateAccountParamsExecutionRegion from .update_account_response import UpdateAccountResponse from .update_app_params import UpdateAppParams from .update_app_response import UpdateAppResponse @@ -214,11 +227,13 @@ from .update_team_member_params_role import UpdateTeamMemberParamsRole from .update_team_member_response import UpdateTeamMemberResponse from .update_team_params import UpdateTeamParams +from .update_team_params_execution_region import UpdateTeamParamsExecutionRegion from .update_team_response import UpdateTeamResponse from .update_user_params import UpdateUserParams from .update_user_response import UpdateUserResponse from .update_webhook_params import UpdateWebhookParams from .update_webhook_response import UpdateWebhookResponse +from .usage_limit import UsageLimit from .user import User from .verified_authenticator import VerifiedAuthenticator from .verify_email_params import VerifyEmailParams @@ -261,6 +276,8 @@ "CreateDeviceLoginTicketResponse", "CreateEnvironmentParams", "CreateEnvironmentResponse", + "CreateGuestParams", + "CreateGuestResponse", "CreatePasswordResetParams", "CreatePasswordResetResponse", "CreateSandboxSecretsParams", @@ -283,6 +300,7 @@ "DeleteAuthenticatorParams", "DeleteAuthenticatorResponse", "DeleteCatalogResponse", + "DeleteGuestOutputBody", "DeleteScheduleParams", "DeleteScheduleResponse", "DeleteSecretResponse", @@ -299,6 +317,7 @@ "DescribeAppResponse", "DescribeAppVersionResponse", "DescribeAuthenticationContextBody", + "DescribeCatalogResponse", "DescribeDeviceLoginSessionResponse", "DescribeEmailPreferencesBody", "DescribePlanResponse", @@ -331,7 +350,9 @@ "GenerateRunStatisticsStatusItem", "GetFeatureFlagResponseBody", "GetFeatureFlagResponseBodyValueType", + "Guest", "InviteTeamMemberParams", + "InviteTeamMemberParamsRole", "InviteTeamMemberResponse", "LeaveTeamResponse", "ListAlertsResponse", @@ -344,6 +365,7 @@ "ListAuthenticatorsResponse", "ListCatalogsResponse", "ListEnvironmentsResponse", + "ListGuestsResponse", "ListMyTeamInvitationsResponse", "ListRunnersResponse", "ListRunsResponse", @@ -356,11 +378,14 @@ "ListTeamsResponse", "ListWebhooksResponse", "Organization", + "OrganizationUsage", "Pagination", "Parameter", "Plan", "RefreshSessionParams", "RefreshSessionResponse", + "RegenerateGuestLoginURLParams", + "RegenerateGuestLoginURLResponse", "RemoveTeamMemberParams", "RemoveTeamMemberResponse", "ResendTeamInvitationParams", @@ -371,6 +396,7 @@ "RunAppParams", "RunAppParamsParameters", "RunAppResponse", + "RunAttempt", "RunFailureAlert", "RunGraphNode", "RunGraphRunID", @@ -381,6 +407,7 @@ "RunnerCredentials", "RunParameter", "RunResults", + "RunRetryPolicy", "RunRunInitiatorDetails", "RunStatistics", "RunStatus", @@ -413,6 +440,7 @@ "Token", "UnverifiedAuthenticator", "UpdateAccountParams", + "UpdateAccountParamsExecutionRegion", "UpdateAccountResponse", "UpdateAppParams", "UpdateAppResponse", @@ -439,11 +467,13 @@ "UpdateTeamMemberParamsRole", "UpdateTeamMemberResponse", "UpdateTeamParams", + "UpdateTeamParamsExecutionRegion", "UpdateTeamResponse", "UpdateUserParams", "UpdateUserResponse", "UpdateWebhookParams", "UpdateWebhookResponse", + "UsageLimit", "User", "VerifiedAuthenticator", "VerifyEmailParams", diff --git a/src/tower/tower_api_client/models/account.py b/src/tower/tower_api_client/models/account.py index 3556710a..19efc05b 100644 --- a/src/tower/tower_api_client/models/account.py +++ b/src/tower/tower_api_client/models/account.py @@ -14,16 +14,20 @@ class Account: """ Attributes: + execution_region (str): is_self_hosted_only (bool): name (str): slug (str | Unset): This property is deprecated. Use name instead. """ + execution_region: str is_self_hosted_only: bool name: str slug: str | Unset = UNSET def to_dict(self) -> dict[str, Any]: + execution_region = self.execution_region + is_self_hosted_only = self.is_self_hosted_only name = self.name @@ -34,6 +38,7 @@ def to_dict(self) -> dict[str, Any]: field_dict.update( { + "execution_region": execution_region, "is_self_hosted_only": is_self_hosted_only, "name": name, } @@ -46,6 +51,8 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + execution_region = d.pop("execution_region") + is_self_hosted_only = d.pop("is_self_hosted_only") name = d.pop("name") @@ -53,6 +60,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: slug = d.pop("slug", UNSET) account = cls( + execution_region=execution_region, is_self_hosted_only=is_self_hosted_only, name=name, slug=slug, diff --git a/src/tower/tower_api_client/models/api_key.py b/src/tower/tower_api_client/models/api_key.py index 8f1d3edb..cffbde33 100644 --- a/src/tower/tower_api_client/models/api_key.py +++ b/src/tower/tower_api_client/models/api_key.py @@ -7,6 +7,8 @@ from attrs import define as _attrs_define from dateutil.parser import isoparse +from ..types import UNSET, Unset + T = TypeVar("T", bound="APIKey") @@ -18,12 +20,16 @@ class APIKey: identifier (str): last_used_at (datetime.datetime | None): name (str): + expires_at (datetime.datetime | Unset): + scopes (str | Unset): """ created_at: datetime.datetime identifier: str last_used_at: datetime.datetime | None name: str + expires_at: datetime.datetime | Unset = UNSET + scopes: str | Unset = UNSET def to_dict(self) -> dict[str, Any]: created_at = self.created_at.isoformat() @@ -38,6 +44,12 @@ def to_dict(self) -> dict[str, Any]: name = self.name + expires_at: str | Unset = UNSET + if not isinstance(self.expires_at, Unset): + expires_at = self.expires_at.isoformat() + + scopes = self.scopes + field_dict: dict[str, Any] = {} field_dict.update( @@ -48,6 +60,10 @@ def to_dict(self) -> dict[str, Any]: "name": name, } ) + if expires_at is not UNSET: + field_dict["expires_at"] = expires_at + if scopes is not UNSET: + field_dict["scopes"] = scopes return field_dict @@ -75,11 +91,22 @@ def _parse_last_used_at(data: object) -> datetime.datetime | None: name = d.pop("name") + _expires_at = d.pop("expires_at", UNSET) + expires_at: datetime.datetime | Unset + if isinstance(_expires_at, Unset): + expires_at = UNSET + else: + expires_at = isoparse(_expires_at) + + scopes = d.pop("scopes", UNSET) + api_key = cls( created_at=created_at, identifier=identifier, last_used_at=last_used_at, name=name, + expires_at=expires_at, + scopes=scopes, ) return api_key diff --git a/src/tower/tower_api_client/models/app.py b/src/tower/tower_api_client/models/app.py index aaab3a19..73d7656b 100644 --- a/src/tower/tower_api_client/models/app.py +++ b/src/tower/tower_api_client/models/app.py @@ -14,6 +14,7 @@ if TYPE_CHECKING: from ..models.run import Run from ..models.run_results import RunResults + from ..models.run_retry_policy import RunRetryPolicy T = TypeVar("T", bound="App") @@ -37,6 +38,7 @@ class App: short_description (str): A short description of the app. Can be empty. version (None | str): The current version of this app, null if none. last_run (Run | Unset): + retry_policy (RunRetryPolicy | Unset): run_results (RunResults | Unset): slug (str | Unset): This property is deprecated. Use name instead. status (AppStatus | Unset): The status of the app. @@ -55,6 +57,7 @@ class App: pending_timeout: int = 600 running_timeout: int = 0 last_run: Run | Unset = UNSET + retry_policy: RunRetryPolicy | Unset = UNSET run_results: RunResults | Unset = UNSET slug: str | Unset = UNSET status: AppStatus | Unset = UNSET @@ -93,6 +96,10 @@ def to_dict(self) -> dict[str, Any]: if not isinstance(self.last_run, Unset): last_run = self.last_run.to_dict() + retry_policy: dict[str, Any] | Unset = UNSET + if not isinstance(self.retry_policy, Unset): + retry_policy = self.retry_policy.to_dict() + run_results: dict[str, Any] | Unset = UNSET if not isinstance(self.run_results, Unset): run_results = self.run_results.to_dict() @@ -124,6 +131,8 @@ def to_dict(self) -> dict[str, Any]: ) if last_run is not UNSET: field_dict["last_run"] = last_run + if retry_policy is not UNSET: + field_dict["retry_policy"] = retry_policy if run_results is not UNSET: field_dict["run_results"] = run_results if slug is not UNSET: @@ -139,6 +148,7 @@ def to_dict(self) -> dict[str, Any]: def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.run import Run from ..models.run_results import RunResults + from ..models.run_retry_policy import RunRetryPolicy d = dict(src_dict) created_at = isoparse(d.pop("created_at")) @@ -193,6 +203,13 @@ def _parse_version(data: object) -> None | str: else: last_run = Run.from_dict(_last_run) + _retry_policy = d.pop("retry_policy", UNSET) + retry_policy: RunRetryPolicy | Unset + if isinstance(_retry_policy, Unset): + retry_policy = UNSET + else: + retry_policy = RunRetryPolicy.from_dict(_retry_policy) + _run_results = d.pop("run_results", UNSET) run_results: RunResults | Unset if isinstance(_run_results, Unset): @@ -224,6 +241,7 @@ def _parse_version(data: object) -> None | str: short_description=short_description, version=version, last_run=last_run, + retry_policy=retry_policy, run_results=run_results, slug=slug, status=status, diff --git a/src/tower/tower_api_client/models/create_api_key_params.py b/src/tower/tower_api_client/models/create_api_key_params.py index c21d6be2..746a5e96 100644 --- a/src/tower/tower_api_client/models/create_api_key_params.py +++ b/src/tower/tower_api_client/models/create_api_key_params.py @@ -1,9 +1,11 @@ from __future__ import annotations +import datetime from collections.abc import Mapping -from typing import Any, TypeVar +from typing import Any, TypeVar, cast from attrs import define as _attrs_define +from dateutil.parser import isoparse from ..types import UNSET, Unset @@ -17,16 +19,44 @@ class CreateAPIKeyParams: name (str): schema (str | Unset): A URL to the JSON Schema for this object. Example: https://api.tower.dev/v1/schemas/CreateAPIKeyParams.json. + expires_at (datetime.datetime | None | Unset): When this API key expires. + scopes (None | str | Unset): Space separated scopes that this API key is valid for. + team (None | str | Unset): The team this API key is associated with. This field is optional. You must be a + member of the team that you're creating the API key for, and if you're using an API key to create a new API key, + the API key you use to authenticate this request must be a personal API key. """ name: str schema: str | Unset = UNSET + expires_at: datetime.datetime | None | Unset = UNSET + scopes: None | str | Unset = UNSET + team: None | str | Unset = UNSET def to_dict(self) -> dict[str, Any]: name = self.name schema = self.schema + expires_at: None | str | Unset + if isinstance(self.expires_at, Unset): + expires_at = UNSET + elif isinstance(self.expires_at, datetime.datetime): + expires_at = self.expires_at.isoformat() + else: + expires_at = self.expires_at + + scopes: None | str | Unset + if isinstance(self.scopes, Unset): + scopes = UNSET + else: + scopes = self.scopes + + team: None | str | Unset + if isinstance(self.team, Unset): + team = UNSET + else: + team = self.team + field_dict: dict[str, Any] = {} field_dict.update( @@ -36,6 +66,12 @@ def to_dict(self) -> dict[str, Any]: ) if schema is not UNSET: field_dict["$schema"] = schema + if expires_at is not UNSET: + field_dict["expires_at"] = expires_at + if scopes is not UNSET: + field_dict["scopes"] = scopes + if team is not UNSET: + field_dict["team"] = team return field_dict @@ -46,9 +82,47 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: schema = d.pop("$schema", UNSET) + def _parse_expires_at(data: object) -> datetime.datetime | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + expires_at_type_0 = isoparse(data) + + return expires_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None | Unset, data) + + expires_at = _parse_expires_at(d.pop("expires_at", UNSET)) + + def _parse_scopes(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + scopes = _parse_scopes(d.pop("scopes", UNSET)) + + def _parse_team(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + team = _parse_team(d.pop("team", UNSET)) + create_api_key_params = cls( name=name, schema=schema, + expires_at=expires_at, + scopes=scopes, + team=team, ) return create_api_key_params diff --git a/src/tower/tower_api_client/models/create_guest_params.py b/src/tower/tower_api_client/models/create_guest_params.py new file mode 100644 index 00000000..bd239c34 --- /dev/null +++ b/src/tower/tower_api_client/models/create_guest_params.py @@ -0,0 +1,82 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="CreateGuestParams") + + +@_attrs_define +class CreateGuestParams: + """ + Attributes: + app (str): The name of the externally accessible app this guest can access. + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/CreateGuestParams.json. + expires_in (int | Unset): The number of seconds the guest session should last. Defaults to 72 hours. Default: + 259200. + name (str | Unset): Optional display name for the guest. + redirect_url (str | Unset): Where to redirect the guest after they log in. Defaults to the app's subdomain. + """ + + app: str + schema: str | Unset = UNSET + expires_in: int | Unset = 259200 + name: str | Unset = UNSET + redirect_url: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + app = self.app + + schema = self.schema + + expires_in = self.expires_in + + name = self.name + + redirect_url = self.redirect_url + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "app": app, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + if expires_in is not UNSET: + field_dict["expires_in"] = expires_in + if name is not UNSET: + field_dict["name"] = name + if redirect_url is not UNSET: + field_dict["redirect_url"] = redirect_url + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + app = d.pop("app") + + schema = d.pop("$schema", UNSET) + + expires_in = d.pop("expires_in", UNSET) + + name = d.pop("name", UNSET) + + redirect_url = d.pop("redirect_url", UNSET) + + create_guest_params = cls( + app=app, + schema=schema, + expires_in=expires_in, + name=name, + redirect_url=redirect_url, + ) + + return create_guest_params diff --git a/src/tower/tower_api_client/models/create_guest_response.py b/src/tower/tower_api_client/models/create_guest_response.py new file mode 100644 index 00000000..2b0f4c1b --- /dev/null +++ b/src/tower/tower_api_client/models/create_guest_response.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from dateutil.parser import isoparse + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.guest import Guest + + +T = TypeVar("T", bound="CreateGuestResponse") + + +@_attrs_define +class CreateGuestResponse: + """ + Attributes: + guest (Guest): + login_url (str): The URL to share with the guest for logging in. + login_url_expires_at (datetime.datetime): When the login URL expires. + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/CreateGuestResponse.json. + """ + + guest: Guest + login_url: str + login_url_expires_at: datetime.datetime + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + guest = self.guest.to_dict() + + login_url = self.login_url + + login_url_expires_at = self.login_url_expires_at.isoformat() + + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "guest": guest, + "login_url": login_url, + "login_url_expires_at": login_url_expires_at, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.guest import Guest + + d = dict(src_dict) + guest = Guest.from_dict(d.pop("guest")) + + login_url = d.pop("login_url") + + login_url_expires_at = isoparse(d.pop("login_url_expires_at")) + + schema = d.pop("$schema", UNSET) + + create_guest_response = cls( + guest=guest, + login_url=login_url, + login_url_expires_at=login_url_expires_at, + schema=schema, + ) + + return create_guest_response diff --git a/src/tower/tower_api_client/models/create_schedule_params.py b/src/tower/tower_api_client/models/create_schedule_params.py index 41d71485..f722db1d 100644 --- a/src/tower/tower_api_client/models/create_schedule_params.py +++ b/src/tower/tower_api_client/models/create_schedule_params.py @@ -35,6 +35,8 @@ class CreateScheduleParams: CreateScheduleParamsOverlapPolicy.ALLOW. parameters (list[RunParameter] | Unset): Parameters to pass when running the app status (CreateScheduleParamsStatus | Unset): The status of the schedule (defaults to active) + timezone (None | str | Unset): The IANA timezone identifier that the cron expression should be evaluated in + (e.g., 'America/New_York', 'Europe/London'). Defaults to 'UTC'. Default: 'UTC'. """ app_name: str @@ -48,6 +50,7 @@ class CreateScheduleParams: ) parameters: list[RunParameter] | Unset = UNSET status: CreateScheduleParamsStatus | Unset = UNSET + timezone: None | str | Unset = "UTC" def to_dict(self) -> dict[str, Any]: app_name = self.app_name @@ -85,6 +88,12 @@ def to_dict(self) -> dict[str, Any]: if not isinstance(self.status, Unset): status = self.status.value + timezone: None | str | Unset + if isinstance(self.timezone, Unset): + timezone = UNSET + else: + timezone = self.timezone + field_dict: dict[str, Any] = {} field_dict.update( @@ -107,6 +116,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["parameters"] = parameters if status is not UNSET: field_dict["status"] = status + if timezone is not UNSET: + field_dict["timezone"] = timezone return field_dict @@ -164,6 +175,15 @@ def _parse_name(data: object) -> None | str | Unset: else: status = CreateScheduleParamsStatus(_status) + def _parse_timezone(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + timezone = _parse_timezone(d.pop("timezone", UNSET)) + create_schedule_params = cls( app_name=app_name, cron=cron, @@ -174,6 +194,7 @@ def _parse_name(data: object) -> None | str | Unset: overlap_policy=overlap_policy, parameters=parameters, status=status, + timezone=timezone, ) return create_schedule_params diff --git a/src/tower/tower_api_client/models/delete_guest_output_body.py b/src/tower/tower_api_client/models/delete_guest_output_body.py new file mode 100644 index 00000000..92e6d613 --- /dev/null +++ b/src/tower/tower_api_client/models/delete_guest_output_body.py @@ -0,0 +1,43 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="DeleteGuestOutputBody") + + +@_attrs_define +class DeleteGuestOutputBody: + """ + Attributes: + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/DeleteGuestOutputBody.json. + """ + + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update({}) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + schema = d.pop("$schema", UNSET) + + delete_guest_output_body = cls( + schema=schema, + ) + + return delete_guest_output_body diff --git a/src/tower/tower_api_client/models/describe_catalog_response.py b/src/tower/tower_api_client/models/describe_catalog_response.py new file mode 100644 index 00000000..a4ff7be9 --- /dev/null +++ b/src/tower/tower_api_client/models/describe_catalog_response.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.catalog import Catalog + + +T = TypeVar("T", bound="DescribeCatalogResponse") + + +@_attrs_define +class DescribeCatalogResponse: + """ + Attributes: + catalog (Catalog): + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/DescribeCatalogResponse.json. + """ + + catalog: Catalog + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + catalog = self.catalog.to_dict() + + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "catalog": catalog, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.catalog import Catalog + + d = dict(src_dict) + catalog = Catalog.from_dict(d.pop("catalog")) + + schema = d.pop("$schema", UNSET) + + describe_catalog_response = cls( + catalog=catalog, + schema=schema, + ) + + return describe_catalog_response diff --git a/src/tower/tower_api_client/models/describe_run_links.py b/src/tower/tower_api_client/models/describe_run_links.py index 4089aead..53fe1471 100644 --- a/src/tower/tower_api_client/models/describe_run_links.py +++ b/src/tower/tower_api_client/models/describe_run_links.py @@ -13,21 +13,31 @@ class DescribeRunLinks: """ Attributes: next_ (None | str): The URL of the next run, if any. + next_number (int | None): The number of the next run, if any. prev (None | str): The URL of the previous run, if any. + prev_number (int | None): The number of the previous run, if any. self_ (str): The URL of this run. """ next_: None | str + next_number: int | None prev: None | str + prev_number: int | None self_: str def to_dict(self) -> dict[str, Any]: next_: None | str next_ = self.next_ + next_number: int | None + next_number = self.next_number + prev: None | str prev = self.prev + prev_number: int | None + prev_number = self.prev_number + self_ = self.self_ field_dict: dict[str, Any] = {} @@ -35,7 +45,9 @@ def to_dict(self) -> dict[str, Any]: field_dict.update( { "next": next_, + "next_number": next_number, "prev": prev, + "prev_number": prev_number, "self": self_, } ) @@ -53,6 +65,13 @@ def _parse_next_(data: object) -> None | str: next_ = _parse_next_(d.pop("next")) + def _parse_next_number(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + next_number = _parse_next_number(d.pop("next_number")) + def _parse_prev(data: object) -> None | str: if data is None: return data @@ -60,11 +79,20 @@ def _parse_prev(data: object) -> None | str: prev = _parse_prev(d.pop("prev")) + def _parse_prev_number(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + prev_number = _parse_prev_number(d.pop("prev_number")) + self_ = d.pop("self") describe_run_links = cls( next_=next_, + next_number=next_number, prev=prev, + prev_number=prev_number, self_=self_, ) diff --git a/src/tower/tower_api_client/models/generate_run_statistics_status_item.py b/src/tower/tower_api_client/models/generate_run_statistics_status_item.py index bde1a4d3..84597b2a 100644 --- a/src/tower/tower_api_client/models/generate_run_statistics_status_item.py +++ b/src/tower/tower_api_client/models/generate_run_statistics_status_item.py @@ -7,6 +7,7 @@ class GenerateRunStatisticsStatusItem(str, Enum): ERRORED = "errored" EXITED = "exited" PENDING = "pending" + RETRYING = "retrying" RUNNING = "running" def __str__(self) -> str: diff --git a/src/tower/tower_api_client/models/guest.py b/src/tower/tower_api_client/models/guest.py new file mode 100644 index 00000000..c8859768 --- /dev/null +++ b/src/tower/tower_api_client/models/guest.py @@ -0,0 +1,71 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from dateutil.parser import isoparse + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="Guest") + + +@_attrs_define +class Guest: + """ + Attributes: + app (str): The name of the app this guest can access. + created_at (datetime.datetime): When the guest was created. + id (str): The unique identifier for the guest. + name (str | Unset): Optional display name for the guest. + """ + + app: str + created_at: datetime.datetime + id: str + name: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + app = self.app + + created_at = self.created_at.isoformat() + + id = self.id + + name = self.name + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "app": app, + "created_at": created_at, + "id": id, + } + ) + if name is not UNSET: + field_dict["name"] = name + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + app = d.pop("app") + + created_at = isoparse(d.pop("created_at")) + + id = d.pop("id") + + name = d.pop("name", UNSET) + + guest = cls( + app=app, + created_at=created_at, + id=id, + name=name, + ) + + return guest diff --git a/src/tower/tower_api_client/models/invite_team_member_params.py b/src/tower/tower_api_client/models/invite_team_member_params.py index 4d09366c..7d651150 100644 --- a/src/tower/tower_api_client/models/invite_team_member_params.py +++ b/src/tower/tower_api_client/models/invite_team_member_params.py @@ -5,6 +5,7 @@ from attrs import define as _attrs_define +from ..models.invite_team_member_params_role import InviteTeamMemberParamsRole from ..types import UNSET, Unset T = TypeVar("T", bound="InviteTeamMemberParams") @@ -16,18 +17,23 @@ class InviteTeamMemberParams: Attributes: emails (str): The email addresses of the people to invite. It can be a list in any format (comma separated, newline separated, etc.) and it will be parsed into individual addresses + role (InviteTeamMemberParamsRole): The role to assign to the invitations Default: + InviteTeamMemberParamsRole.DEVELOPER. schema (str | Unset): A URL to the JSON Schema for this object. Example: https://api.tower.dev/v1/schemas/InviteTeamMemberParams.json. message (str | Unset): Optional message to include in the invite email """ emails: str + role: InviteTeamMemberParamsRole = InviteTeamMemberParamsRole.DEVELOPER schema: str | Unset = UNSET message: str | Unset = UNSET def to_dict(self) -> dict[str, Any]: emails = self.emails + role = self.role.value + schema = self.schema message = self.message @@ -37,6 +43,7 @@ def to_dict(self) -> dict[str, Any]: field_dict.update( { "emails": emails, + "role": role, } ) if schema is not UNSET: @@ -51,12 +58,15 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) emails = d.pop("emails") + role = InviteTeamMemberParamsRole(d.pop("role")) + schema = d.pop("$schema", UNSET) message = d.pop("message", UNSET) invite_team_member_params = cls( emails=emails, + role=role, schema=schema, message=message, ) diff --git a/src/tower/tower_api_client/models/invite_team_member_params_role.py b/src/tower/tower_api_client/models/invite_team_member_params_role.py new file mode 100644 index 00000000..d238fd86 --- /dev/null +++ b/src/tower/tower_api_client/models/invite_team_member_params_role.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class InviteTeamMemberParamsRole(str, Enum): + ADMIN = "admin" + DEVELOPER = "developer" + + def __str__(self) -> str: + return str(self.value) diff --git a/src/tower/tower_api_client/models/list_guests_response.py b/src/tower/tower_api_client/models/list_guests_response.py new file mode 100644 index 00000000..d574a7cb --- /dev/null +++ b/src/tower/tower_api_client/models/list_guests_response.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.guest import Guest + + +T = TypeVar("T", bound="ListGuestsResponse") + + +@_attrs_define +class ListGuestsResponse: + """ + Attributes: + guests (list[Guest]): List of guests. + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/ListGuestsResponse.json. + """ + + guests: list[Guest] + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + guests = [] + for guests_item_data in self.guests: + guests_item = guests_item_data.to_dict() + guests.append(guests_item) + + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "guests": guests, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.guest import Guest + + d = dict(src_dict) + guests = [] + _guests = d.pop("guests") + for guests_item_data in _guests: + guests_item = Guest.from_dict(guests_item_data) + + guests.append(guests_item) + + schema = d.pop("$schema", UNSET) + + list_guests_response = cls( + guests=guests, + schema=schema, + ) + + return list_guests_response diff --git a/src/tower/tower_api_client/models/list_runs_status_item.py b/src/tower/tower_api_client/models/list_runs_status_item.py index c33e30d8..46671e20 100644 --- a/src/tower/tower_api_client/models/list_runs_status_item.py +++ b/src/tower/tower_api_client/models/list_runs_status_item.py @@ -7,6 +7,7 @@ class ListRunsStatusItem(str, Enum): ERRORED = "errored" EXITED = "exited" PENDING = "pending" + RETRYING = "retrying" RUNNING = "running" def __str__(self) -> str: diff --git a/src/tower/tower_api_client/models/organization_usage.py b/src/tower/tower_api_client/models/organization_usage.py new file mode 100644 index 00000000..74bda4e3 --- /dev/null +++ b/src/tower/tower_api_client/models/organization_usage.py @@ -0,0 +1,108 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.usage_limit import UsageLimit + + +T = TypeVar("T", bound="OrganizationUsage") + + +@_attrs_define +class OrganizationUsage: + """ + Attributes: + active_schedules (UsageLimit): + apps (UsageLimit): + base_plan_name (str): The name of the organization's base plan. + compute_minutes (UsageLimit): + members (UsageLimit): + organization_name (str): The name of the organization. + self_hosted_runners (UsageLimit): + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/OrganizationUsage.json. + """ + + active_schedules: UsageLimit + apps: UsageLimit + base_plan_name: str + compute_minutes: UsageLimit + members: UsageLimit + organization_name: str + self_hosted_runners: UsageLimit + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + active_schedules = self.active_schedules.to_dict() + + apps = self.apps.to_dict() + + base_plan_name = self.base_plan_name + + compute_minutes = self.compute_minutes.to_dict() + + members = self.members.to_dict() + + organization_name = self.organization_name + + self_hosted_runners = self.self_hosted_runners.to_dict() + + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "active_schedules": active_schedules, + "apps": apps, + "base_plan_name": base_plan_name, + "compute_minutes": compute_minutes, + "members": members, + "organization_name": organization_name, + "self_hosted_runners": self_hosted_runners, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.usage_limit import UsageLimit + + d = dict(src_dict) + active_schedules = UsageLimit.from_dict(d.pop("active_schedules")) + + apps = UsageLimit.from_dict(d.pop("apps")) + + base_plan_name = d.pop("base_plan_name") + + compute_minutes = UsageLimit.from_dict(d.pop("compute_minutes")) + + members = UsageLimit.from_dict(d.pop("members")) + + organization_name = d.pop("organization_name") + + self_hosted_runners = UsageLimit.from_dict(d.pop("self_hosted_runners")) + + schema = d.pop("$schema", UNSET) + + organization_usage = cls( + active_schedules=active_schedules, + apps=apps, + base_plan_name=base_plan_name, + compute_minutes=compute_minutes, + members=members, + organization_name=organization_name, + self_hosted_runners=self_hosted_runners, + schema=schema, + ) + + return organization_usage diff --git a/src/tower/tower_api_client/models/parameter.py b/src/tower/tower_api_client/models/parameter.py index fb161761..131d5881 100644 --- a/src/tower/tower_api_client/models/parameter.py +++ b/src/tower/tower_api_client/models/parameter.py @@ -5,6 +5,8 @@ from attrs import define as _attrs_define +from ..types import UNSET, Unset + T = TypeVar("T", bound="Parameter") @@ -15,11 +17,13 @@ class Parameter: default (str): description (str): name (str): + hidden (bool | Unset): Whether this parameter is hidden/secret. Defaults to false. Default: False. """ default: str description: str name: str + hidden: bool | Unset = False def to_dict(self) -> dict[str, Any]: default = self.default @@ -28,6 +32,8 @@ def to_dict(self) -> dict[str, Any]: name = self.name + hidden = self.hidden + field_dict: dict[str, Any] = {} field_dict.update( @@ -37,6 +43,8 @@ def to_dict(self) -> dict[str, Any]: "name": name, } ) + if hidden is not UNSET: + field_dict["hidden"] = hidden return field_dict @@ -49,10 +57,13 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: name = d.pop("name") + hidden = d.pop("hidden", UNSET) + parameter = cls( default=default, description=description, name=name, + hidden=hidden, ) return parameter diff --git a/src/tower/tower_api_client/models/regenerate_guest_login_url_params.py b/src/tower/tower_api_client/models/regenerate_guest_login_url_params.py new file mode 100644 index 00000000..7d8caf40 --- /dev/null +++ b/src/tower/tower_api_client/models/regenerate_guest_login_url_params.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="RegenerateGuestLoginURLParams") + + +@_attrs_define +class RegenerateGuestLoginURLParams: + """ + Attributes: + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/RegenerateGuestLoginURLParams.json. + expires_in (int | Unset): The number of seconds the guest session should last. Defaults to 72 hours. Default: + 259200. + redirect_url (str | Unset): Where to redirect the guest after they log in. + """ + + schema: str | Unset = UNSET + expires_in: int | Unset = 259200 + redirect_url: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + schema = self.schema + + expires_in = self.expires_in + + redirect_url = self.redirect_url + + field_dict: dict[str, Any] = {} + + field_dict.update({}) + if schema is not UNSET: + field_dict["$schema"] = schema + if expires_in is not UNSET: + field_dict["expires_in"] = expires_in + if redirect_url is not UNSET: + field_dict["redirect_url"] = redirect_url + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + schema = d.pop("$schema", UNSET) + + expires_in = d.pop("expires_in", UNSET) + + redirect_url = d.pop("redirect_url", UNSET) + + regenerate_guest_login_url_params = cls( + schema=schema, + expires_in=expires_in, + redirect_url=redirect_url, + ) + + return regenerate_guest_login_url_params diff --git a/src/tower/tower_api_client/models/regenerate_guest_login_url_response.py b/src/tower/tower_api_client/models/regenerate_guest_login_url_response.py new file mode 100644 index 00000000..062f0623 --- /dev/null +++ b/src/tower/tower_api_client/models/regenerate_guest_login_url_response.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from dateutil.parser import isoparse + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="RegenerateGuestLoginURLResponse") + + +@_attrs_define +class RegenerateGuestLoginURLResponse: + """ + Attributes: + login_url (str): The new login URL to share with the guest. + login_url_expires_at (datetime.datetime): When the login URL expires. + schema (str | Unset): A URL to the JSON Schema for this object. Example: + https://api.tower.dev/v1/schemas/RegenerateGuestLoginURLResponse.json. + """ + + login_url: str + login_url_expires_at: datetime.datetime + schema: str | Unset = UNSET + + def to_dict(self) -> dict[str, Any]: + login_url = self.login_url + + login_url_expires_at = self.login_url_expires_at.isoformat() + + schema = self.schema + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "login_url": login_url, + "login_url_expires_at": login_url_expires_at, + } + ) + if schema is not UNSET: + field_dict["$schema"] = schema + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + login_url = d.pop("login_url") + + login_url_expires_at = isoparse(d.pop("login_url_expires_at")) + + schema = d.pop("$schema", UNSET) + + regenerate_guest_login_url_response = cls( + login_url=login_url, + login_url_expires_at=login_url_expires_at, + schema=schema, + ) + + return regenerate_guest_login_url_response diff --git a/src/tower/tower_api_client/models/run.py b/src/tower/tower_api_client/models/run.py index 17fd56ae..3eb0219b 100644 --- a/src/tower/tower_api_client/models/run.py +++ b/src/tower/tower_api_client/models/run.py @@ -12,8 +12,10 @@ from ..types import UNSET, Unset if TYPE_CHECKING: + from ..models.run_attempt import RunAttempt from ..models.run_initiator import RunInitiator from ..models.run_parameter import RunParameter + from ..models.run_retry_policy import RunRetryPolicy T = TypeVar("T", bound="Run") @@ -34,6 +36,7 @@ class Run: initiator (RunInitiator): is_scheduled (bool): Whether this run was triggered by a schedule (true) or on-demand (false). Historical records default to false. + num_attempts (int): Number of attempts for this run (1 = original, 2+ = retries). number (int): parameters (list[RunParameter]): Parameters used to invoke this run. run_id (str): @@ -42,7 +45,9 @@ class Run: status (RunStatus): status_group (RunStatusGroup): app_slug (str | Unset): This property is deprecated. Use app_name instead. + attempts (list[RunAttempt] | Unset): Previous attempt details. Populated on describe, omitted on list. hostname (str | Unset): hostname is deprecated, use subdomain + retry_policy (RunRetryPolicy | Unset): subdomain (None | str | Unset): If app is externally accessible, then you can access this run with this hostname. """ @@ -57,6 +62,7 @@ class Run: exit_code: int | None initiator: RunInitiator is_scheduled: bool + num_attempts: int number: int parameters: list[RunParameter] run_id: str @@ -65,7 +71,9 @@ class Run: status: RunStatus status_group: RunStatusGroup app_slug: str | Unset = UNSET + attempts: list[RunAttempt] | Unset = UNSET hostname: str | Unset = UNSET + retry_policy: RunRetryPolicy | Unset = UNSET subdomain: None | str | Unset = UNSET def to_dict(self) -> dict[str, Any]: @@ -98,6 +106,8 @@ def to_dict(self) -> dict[str, Any]: is_scheduled = self.is_scheduled + num_attempts = self.num_attempts + number = self.number parameters = [] @@ -121,8 +131,19 @@ def to_dict(self) -> dict[str, Any]: app_slug = self.app_slug + attempts: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.attempts, Unset): + attempts = [] + for attempts_item_data in self.attempts: + attempts_item = attempts_item_data.to_dict() + attempts.append(attempts_item) + hostname = self.hostname + retry_policy: dict[str, Any] | Unset = UNSET + if not isinstance(self.retry_policy, Unset): + retry_policy = self.retry_policy.to_dict() + subdomain: None | str | Unset if isinstance(self.subdomain, Unset): subdomain = UNSET @@ -143,6 +164,7 @@ def to_dict(self) -> dict[str, Any]: "exit_code": exit_code, "initiator": initiator, "is_scheduled": is_scheduled, + "num_attempts": num_attempts, "number": number, "parameters": parameters, "run_id": run_id, @@ -154,8 +176,12 @@ def to_dict(self) -> dict[str, Any]: ) if app_slug is not UNSET: field_dict["app_slug"] = app_slug + if attempts is not UNSET: + field_dict["attempts"] = attempts if hostname is not UNSET: field_dict["hostname"] = hostname + if retry_policy is not UNSET: + field_dict["retry_policy"] = retry_policy if subdomain is not UNSET: field_dict["subdomain"] = subdomain @@ -163,8 +189,10 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.run_attempt import RunAttempt from ..models.run_initiator import RunInitiator from ..models.run_parameter import RunParameter + from ..models.run_retry_policy import RunRetryPolicy d = dict(src_dict) link = d.pop("$link") @@ -218,6 +246,8 @@ def _parse_exit_code(data: object) -> int | None: is_scheduled = d.pop("is_scheduled") + num_attempts = d.pop("num_attempts") + number = d.pop("number") parameters = [] @@ -252,8 +282,24 @@ def _parse_started_at(data: object) -> datetime.datetime | None: app_slug = d.pop("app_slug", UNSET) + _attempts = d.pop("attempts", UNSET) + attempts: list[RunAttempt] | Unset = UNSET + if _attempts is not UNSET: + attempts = [] + for attempts_item_data in _attempts: + attempts_item = RunAttempt.from_dict(attempts_item_data) + + attempts.append(attempts_item) + hostname = d.pop("hostname", UNSET) + _retry_policy = d.pop("retry_policy", UNSET) + retry_policy: RunRetryPolicy | Unset + if isinstance(_retry_policy, Unset): + retry_policy = UNSET + else: + retry_policy = RunRetryPolicy.from_dict(_retry_policy) + def _parse_subdomain(data: object) -> None | str | Unset: if data is None: return data @@ -274,6 +320,7 @@ def _parse_subdomain(data: object) -> None | str | Unset: exit_code=exit_code, initiator=initiator, is_scheduled=is_scheduled, + num_attempts=num_attempts, number=number, parameters=parameters, run_id=run_id, @@ -282,7 +329,9 @@ def _parse_subdomain(data: object) -> None | str | Unset: status=status, status_group=status_group, app_slug=app_slug, + attempts=attempts, hostname=hostname, + retry_policy=retry_policy, subdomain=subdomain, ) diff --git a/src/tower/tower_api_client/models/run_app_params.py b/src/tower/tower_api_client/models/run_app_params.py index 21a6d82e..943b4a12 100644 --- a/src/tower/tower_api_client/models/run_app_params.py +++ b/src/tower/tower_api_client/models/run_app_params.py @@ -10,6 +10,7 @@ if TYPE_CHECKING: from ..models.run_app_initiator_data import RunAppInitiatorData from ..models.run_app_params_parameters import RunAppParamsParameters + from ..models.run_retry_policy import RunRetryPolicy T = TypeVar("T", bound="RunAppParams") @@ -26,6 +27,7 @@ class RunAppParams: initiator (RunAppInitiatorData | Unset): parent_run_id (None | str | Unset): The ID of the run that invoked this run, if relevant. Should be null, if none. + retry_policy (RunRetryPolicy | Unset): """ environment: str @@ -33,6 +35,7 @@ class RunAppParams: schema: str | Unset = UNSET initiator: RunAppInitiatorData | Unset = UNSET parent_run_id: None | str | Unset = UNSET + retry_policy: RunRetryPolicy | Unset = UNSET def to_dict(self) -> dict[str, Any]: environment = self.environment @@ -51,6 +54,10 @@ def to_dict(self) -> dict[str, Any]: else: parent_run_id = self.parent_run_id + retry_policy: dict[str, Any] | Unset = UNSET + if not isinstance(self.retry_policy, Unset): + retry_policy = self.retry_policy.to_dict() + field_dict: dict[str, Any] = {} field_dict.update( @@ -65,6 +72,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["initiator"] = initiator if parent_run_id is not UNSET: field_dict["parent_run_id"] = parent_run_id + if retry_policy is not UNSET: + field_dict["retry_policy"] = retry_policy return field_dict @@ -72,6 +81,7 @@ def to_dict(self) -> dict[str, Any]: def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.run_app_initiator_data import RunAppInitiatorData from ..models.run_app_params_parameters import RunAppParamsParameters + from ..models.run_retry_policy import RunRetryPolicy d = dict(src_dict) environment = d.pop("environment") @@ -96,12 +106,20 @@ def _parse_parent_run_id(data: object) -> None | str | Unset: parent_run_id = _parse_parent_run_id(d.pop("parent_run_id", UNSET)) + _retry_policy = d.pop("retry_policy", UNSET) + retry_policy: RunRetryPolicy | Unset + if isinstance(_retry_policy, Unset): + retry_policy = UNSET + else: + retry_policy = RunRetryPolicy.from_dict(_retry_policy) + run_app_params = cls( environment=environment, parameters=parameters, schema=schema, initiator=initiator, parent_run_id=parent_run_id, + retry_policy=retry_policy, ) return run_app_params diff --git a/src/tower/tower_api_client/models/run_attempt.py b/src/tower/tower_api_client/models/run_attempt.py new file mode 100644 index 00000000..da912e6d --- /dev/null +++ b/src/tower/tower_api_client/models/run_attempt.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from dateutil.parser import isoparse + +T = TypeVar("T", bound="RunAttempt") + + +@_attrs_define +class RunAttempt: + """ + Attributes: + ended_at (datetime.datetime | None): When this attempt ended. + exit_code (int | None): Exit code for this attempt. + seq (int): 1-based attempt number. + started_at (datetime.datetime | None): When this attempt started. + status (str): Terminal status of this attempt. + """ + + ended_at: datetime.datetime | None + exit_code: int | None + seq: int + started_at: datetime.datetime | None + status: str + + def to_dict(self) -> dict[str, Any]: + ended_at: None | str + if isinstance(self.ended_at, datetime.datetime): + ended_at = self.ended_at.isoformat() + else: + ended_at = self.ended_at + + exit_code: int | None + exit_code = self.exit_code + + seq = self.seq + + started_at: None | str + if isinstance(self.started_at, datetime.datetime): + started_at = self.started_at.isoformat() + else: + started_at = self.started_at + + status = self.status + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "ended_at": ended_at, + "exit_code": exit_code, + "seq": seq, + "started_at": started_at, + "status": status, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + + def _parse_ended_at(data: object) -> datetime.datetime | None: + if data is None: + return data + try: + if not isinstance(data, str): + raise TypeError() + ended_at_type_0 = isoparse(data) + + return ended_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None, data) + + ended_at = _parse_ended_at(d.pop("ended_at")) + + def _parse_exit_code(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + exit_code = _parse_exit_code(d.pop("exit_code")) + + seq = d.pop("seq") + + def _parse_started_at(data: object) -> datetime.datetime | None: + if data is None: + return data + try: + if not isinstance(data, str): + raise TypeError() + started_at_type_0 = isoparse(data) + + return started_at_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.datetime | None, data) + + started_at = _parse_started_at(d.pop("started_at")) + + status = d.pop("status") + + run_attempt = cls( + ended_at=ended_at, + exit_code=exit_code, + seq=seq, + started_at=started_at, + status=status, + ) + + return run_attempt diff --git a/src/tower/tower_api_client/models/run_log_line.py b/src/tower/tower_api_client/models/run_log_line.py index 7d6fcab6..01ecc67c 100644 --- a/src/tower/tower_api_client/models/run_log_line.py +++ b/src/tower/tower_api_client/models/run_log_line.py @@ -17,6 +17,8 @@ class RunLogLine: """ Attributes: + attempt_seq (int): The attempt number this log line belongs to (1-based). Attempt 1 is the original execution; + 2+ are retries. channel (RunLogLineChannel): The channel this log line belongs to. content (str): Contents of the log message. line_num (int): Line number. @@ -26,6 +28,7 @@ class RunLogLine: timestamp (datetime.datetime | Unset): This property is deprecated. Use reported_at instead. """ + attempt_seq: int channel: RunLogLineChannel content: str line_num: int @@ -35,6 +38,8 @@ class RunLogLine: timestamp: datetime.datetime | Unset = UNSET def to_dict(self) -> dict[str, Any]: + attempt_seq = self.attempt_seq + channel = self.channel.value content = self.content @@ -55,6 +60,7 @@ def to_dict(self) -> dict[str, Any]: field_dict.update( { + "attempt_seq": attempt_seq, "channel": channel, "content": content, "line_num": line_num, @@ -72,6 +78,8 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + attempt_seq = d.pop("attempt_seq") + channel = RunLogLineChannel(d.pop("channel")) content = d.pop("content") @@ -92,6 +100,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: timestamp = isoparse(_timestamp) run_log_line = cls( + attempt_seq=attempt_seq, channel=channel, content=content, line_num=line_num, diff --git a/src/tower/tower_api_client/models/run_parameter.py b/src/tower/tower_api_client/models/run_parameter.py index 5089c844..f668ccc1 100644 --- a/src/tower/tower_api_client/models/run_parameter.py +++ b/src/tower/tower_api_client/models/run_parameter.py @@ -5,6 +5,8 @@ from attrs import define as _attrs_define +from ..types import UNSET, Unset + T = TypeVar("T", bound="RunParameter") @@ -14,16 +16,20 @@ class RunParameter: Attributes: name (str): value (str): + hidden (bool | Unset): Whether this parameter is hidden/secret. Defaults to false. Default: False. """ name: str value: str + hidden: bool | Unset = False def to_dict(self) -> dict[str, Any]: name = self.name value = self.value + hidden = self.hidden + field_dict: dict[str, Any] = {} field_dict.update( @@ -32,6 +38,8 @@ def to_dict(self) -> dict[str, Any]: "value": value, } ) + if hidden is not UNSET: + field_dict["hidden"] = hidden return field_dict @@ -42,9 +50,12 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: value = d.pop("value") + hidden = d.pop("hidden", UNSET) + run_parameter = cls( name=name, value=value, + hidden=hidden, ) return run_parameter diff --git a/src/tower/tower_api_client/models/run_results.py b/src/tower/tower_api_client/models/run_results.py index c3d1e24c..37c69711 100644 --- a/src/tower/tower_api_client/models/run_results.py +++ b/src/tower/tower_api_client/models/run_results.py @@ -17,6 +17,7 @@ class RunResults: errored (int): exited (int): pending (int): + retrying (int): running (int): """ @@ -25,6 +26,7 @@ class RunResults: errored: int exited: int pending: int + retrying: int running: int def to_dict(self) -> dict[str, Any]: @@ -38,6 +40,8 @@ def to_dict(self) -> dict[str, Any]: pending = self.pending + retrying = self.retrying + running = self.running field_dict: dict[str, Any] = {} @@ -49,6 +53,7 @@ def to_dict(self) -> dict[str, Any]: "errored": errored, "exited": exited, "pending": pending, + "retrying": retrying, "running": running, } ) @@ -68,6 +73,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: pending = d.pop("pending") + retrying = d.pop("retrying") + running = d.pop("running") run_results = cls( @@ -76,6 +83,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: errored=errored, exited=exited, pending=pending, + retrying=retrying, running=running, ) diff --git a/src/tower/tower_api_client/models/run_retry_policy.py b/src/tower/tower_api_client/models/run_retry_policy.py new file mode 100644 index 00000000..bcc3db09 --- /dev/null +++ b/src/tower/tower_api_client/models/run_retry_policy.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define + +T = TypeVar("T", bound="RunRetryPolicy") + + +@_attrs_define +class RunRetryPolicy: + """ + Attributes: + max_retries (int): + retry_delay_seconds (int): + use_exponential_backoff (bool): + """ + + max_retries: int + retry_delay_seconds: int + use_exponential_backoff: bool + + def to_dict(self) -> dict[str, Any]: + max_retries = self.max_retries + + retry_delay_seconds = self.retry_delay_seconds + + use_exponential_backoff = self.use_exponential_backoff + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "max_retries": max_retries, + "retry_delay_seconds": retry_delay_seconds, + "use_exponential_backoff": use_exponential_backoff, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + max_retries = d.pop("max_retries") + + retry_delay_seconds = d.pop("retry_delay_seconds") + + use_exponential_backoff = d.pop("use_exponential_backoff") + + run_retry_policy = cls( + max_retries=max_retries, + retry_delay_seconds=retry_delay_seconds, + use_exponential_backoff=use_exponential_backoff, + ) + + return run_retry_policy diff --git a/src/tower/tower_api_client/models/run_status.py b/src/tower/tower_api_client/models/run_status.py index c640e7e7..1cad2eb3 100644 --- a/src/tower/tower_api_client/models/run_status.py +++ b/src/tower/tower_api_client/models/run_status.py @@ -7,6 +7,7 @@ class RunStatus(str, Enum): ERRORED = "errored" EXITED = "exited" PENDING = "pending" + RETRYING = "retrying" RUNNING = "running" SCHEDULED = "scheduled" diff --git a/src/tower/tower_api_client/models/run_timeseries_point.py b/src/tower/tower_api_client/models/run_timeseries_point.py index 39d127b1..de83c155 100644 --- a/src/tower/tower_api_client/models/run_timeseries_point.py +++ b/src/tower/tower_api_client/models/run_timeseries_point.py @@ -20,6 +20,7 @@ class RunTimeseriesPoint: exited (int): pending (int): period (datetime.datetime): The period of the timeseries point, typically the start of the period. + retrying (int): running (int): scheduled (int): """ @@ -30,6 +31,7 @@ class RunTimeseriesPoint: exited: int pending: int period: datetime.datetime + retrying: int running: int scheduled: int @@ -46,6 +48,8 @@ def to_dict(self) -> dict[str, Any]: period = self.period.isoformat() + retrying = self.retrying + running = self.running scheduled = self.scheduled @@ -60,6 +64,7 @@ def to_dict(self) -> dict[str, Any]: "exited": exited, "pending": pending, "period": period, + "retrying": retrying, "running": running, "scheduled": scheduled, } @@ -82,6 +87,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: period = isoparse(d.pop("period")) + retrying = d.pop("retrying") + running = d.pop("running") scheduled = d.pop("scheduled") @@ -93,6 +100,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: exited=exited, pending=pending, period=period, + retrying=retrying, running=running, scheduled=scheduled, ) diff --git a/src/tower/tower_api_client/models/runner.py b/src/tower/tower_api_client/models/runner.py index 00d718b3..668afb5d 100644 --- a/src/tower/tower_api_client/models/runner.py +++ b/src/tower/tower_api_client/models/runner.py @@ -25,6 +25,7 @@ class Runner: num_runs (int): status (str): last_health_check_at (str | Unset): + name (str | Unset): Optional human-readable name for the runner """ active_runs: list[Run] @@ -34,6 +35,7 @@ class Runner: num_runs: int status: str last_health_check_at: str | Unset = UNSET + name: str | Unset = UNSET def to_dict(self) -> dict[str, Any]: active_runs = [] @@ -53,6 +55,8 @@ def to_dict(self) -> dict[str, Any]: last_health_check_at = self.last_health_check_at + name = self.name + field_dict: dict[str, Any] = {} field_dict.update( @@ -67,6 +71,8 @@ def to_dict(self) -> dict[str, Any]: ) if last_health_check_at is not UNSET: field_dict["last_health_check_at"] = last_health_check_at + if name is not UNSET: + field_dict["name"] = name return field_dict @@ -94,6 +100,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: last_health_check_at = d.pop("last_health_check_at", UNSET) + name = d.pop("name", UNSET) + runner = cls( active_runs=active_runs, created_at=created_at, @@ -102,6 +110,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: num_runs=num_runs, status=status, last_health_check_at=last_health_check_at, + name=name, ) return runner diff --git a/src/tower/tower_api_client/models/schedule.py b/src/tower/tower_api_client/models/schedule.py index ed44493a..42f77665 100644 --- a/src/tower/tower_api_client/models/schedule.py +++ b/src/tower/tower_api_client/models/schedule.py @@ -32,6 +32,8 @@ class Schedule: name (str): The name of this schedule overlap_policy (ScheduleOverlapPolicy): The policy for handling overlapping runs status (ScheduleStatus): The status of the schedule + timezone (str): The IANA timezone identifier that the cron expression is evaluated in (e.g., 'America/New_York', + 'Europe/London'). Defaults to 'UTC'. updated_at (datetime.datetime): The timestamp when the schedule was last updated app_version (str | Unset): The specific app version to run, or null for the default version parameters (list[RunParameter] | Unset): The parameters to pass when running the app @@ -46,6 +48,7 @@ class Schedule: name: str overlap_policy: ScheduleOverlapPolicy status: ScheduleStatus + timezone: str updated_at: datetime.datetime app_version: str | Unset = UNSET parameters: list[RunParameter] | Unset = UNSET @@ -69,6 +72,8 @@ def to_dict(self) -> dict[str, Any]: status = self.status.value + timezone = self.timezone + updated_at = self.updated_at.isoformat() app_version = self.app_version @@ -93,6 +98,7 @@ def to_dict(self) -> dict[str, Any]: "name": name, "overlap_policy": overlap_policy, "status": status, + "timezone": timezone, "updated_at": updated_at, } ) @@ -126,6 +132,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: status = ScheduleStatus(d.pop("status")) + timezone = d.pop("timezone") + updated_at = isoparse(d.pop("updated_at")) app_version = d.pop("app_version", UNSET) @@ -149,6 +157,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: name=name, overlap_policy=overlap_policy, status=status, + timezone=timezone, updated_at=updated_at, app_version=app_version, parameters=parameters, diff --git a/src/tower/tower_api_client/models/search_runs_status_item.py b/src/tower/tower_api_client/models/search_runs_status_item.py index 1a6b09a4..afac0331 100644 --- a/src/tower/tower_api_client/models/search_runs_status_item.py +++ b/src/tower/tower_api_client/models/search_runs_status_item.py @@ -7,6 +7,7 @@ class SearchRunsStatusItem(str, Enum): ERRORED = "errored" EXITED = "exited" PENDING = "pending" + RETRYING = "retrying" RUNNING = "running" def __str__(self) -> str: diff --git a/src/tower/tower_api_client/models/team.py b/src/tower/tower_api_client/models/team.py index 7a834d75..21d8eebd 100644 --- a/src/tower/tower_api_client/models/team.py +++ b/src/tower/tower_api_client/models/team.py @@ -18,20 +18,28 @@ class Team: """ Attributes: + execution_region (str): name (str): + organization (str): The name of the organization this team belongs to. type_ (str): The type of team, either 'personal' or 'team'. slug (str | Unset): This property is deprecated. Use name instead. token (Token | Unset): """ + execution_region: str name: str + organization: str type_: str slug: str | Unset = UNSET token: Token | Unset = UNSET def to_dict(self) -> dict[str, Any]: + execution_region = self.execution_region + name = self.name + organization = self.organization + type_ = self.type_ slug = self.slug @@ -44,7 +52,9 @@ def to_dict(self) -> dict[str, Any]: field_dict.update( { + "execution_region": execution_region, "name": name, + "organization": organization, "type": type_, } ) @@ -60,8 +70,12 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.token import Token d = dict(src_dict) + execution_region = d.pop("execution_region") + name = d.pop("name") + organization = d.pop("organization") + type_ = d.pop("type") slug = d.pop("slug", UNSET) @@ -74,7 +88,9 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: token = Token.from_dict(_token) team = cls( + execution_region=execution_region, name=name, + organization=organization, type_=type_, slug=slug, token=token, diff --git a/src/tower/tower_api_client/models/team_invitation.py b/src/tower/tower_api_client/models/team_invitation.py index f83c7203..b253abef 100644 --- a/src/tower/tower_api_client/models/team_invitation.py +++ b/src/tower/tower_api_client/models/team_invitation.py @@ -7,8 +7,6 @@ from attrs import define as _attrs_define from dateutil.parser import isoparse -from ..types import UNSET, Unset - if TYPE_CHECKING: from ..models.team import Team @@ -22,29 +20,23 @@ class TeamInvitation: Attributes: email (str): invitation_sent_at (datetime.datetime): + role (str): team (Team): - target_organization_name (str | Unset): The name of the organization the user will move to if they accept this - invitation - will_change_organization (bool | Unset): Indicates if accepting this invitation will move the user to a - different organization """ email: str invitation_sent_at: datetime.datetime + role: str team: Team - target_organization_name: str | Unset = UNSET - will_change_organization: bool | Unset = UNSET def to_dict(self) -> dict[str, Any]: email = self.email invitation_sent_at = self.invitation_sent_at.isoformat() - team = self.team.to_dict() - - target_organization_name = self.target_organization_name + role = self.role - will_change_organization = self.will_change_organization + team = self.team.to_dict() field_dict: dict[str, Any] = {} @@ -52,13 +44,10 @@ def to_dict(self) -> dict[str, Any]: { "email": email, "invitation_sent_at": invitation_sent_at, + "role": role, "team": team, } ) - if target_organization_name is not UNSET: - field_dict["target_organization_name"] = target_organization_name - if will_change_organization is not UNSET: - field_dict["will_change_organization"] = will_change_organization return field_dict @@ -71,18 +60,15 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: invitation_sent_at = isoparse(d.pop("invitation_sent_at")) - team = Team.from_dict(d.pop("team")) - - target_organization_name = d.pop("target_organization_name", UNSET) + role = d.pop("role") - will_change_organization = d.pop("will_change_organization", UNSET) + team = Team.from_dict(d.pop("team")) team_invitation = cls( email=email, invitation_sent_at=invitation_sent_at, + role=role, team=team, - target_organization_name=target_organization_name, - will_change_organization=will_change_organization, ) return team_invitation diff --git a/src/tower/tower_api_client/models/update_account_params.py b/src/tower/tower_api_client/models/update_account_params.py index 60fe36d1..d59cdf63 100644 --- a/src/tower/tower_api_client/models/update_account_params.py +++ b/src/tower/tower_api_client/models/update_account_params.py @@ -5,6 +5,9 @@ from attrs import define as _attrs_define +from ..models.update_account_params_execution_region import ( + UpdateAccountParamsExecutionRegion, +) from ..types import UNSET, Unset T = TypeVar("T", bound="UpdateAccountParams") @@ -16,17 +19,24 @@ class UpdateAccountParams: Attributes: schema (str | Unset): A URL to the JSON Schema for this object. Example: https://api.tower.dev/v1/schemas/UpdateAccountParams.json. + execution_region (UpdateAccountParamsExecutionRegion | Unset): The execution region for runs (eu-central-1 or + us-east-1) is_self_hosted_only (bool | Unset): Whether the account is for self-hosted use only name (str | Unset): The new name for the account, if any """ schema: str | Unset = UNSET + execution_region: UpdateAccountParamsExecutionRegion | Unset = UNSET is_self_hosted_only: bool | Unset = UNSET name: str | Unset = UNSET def to_dict(self) -> dict[str, Any]: schema = self.schema + execution_region: str | Unset = UNSET + if not isinstance(self.execution_region, Unset): + execution_region = self.execution_region.value + is_self_hosted_only = self.is_self_hosted_only name = self.name @@ -36,6 +46,8 @@ def to_dict(self) -> dict[str, Any]: field_dict.update({}) if schema is not UNSET: field_dict["$schema"] = schema + if execution_region is not UNSET: + field_dict["execution_region"] = execution_region if is_self_hosted_only is not UNSET: field_dict["is_self_hosted_only"] = is_self_hosted_only if name is not UNSET: @@ -48,12 +60,20 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) schema = d.pop("$schema", UNSET) + _execution_region = d.pop("execution_region", UNSET) + execution_region: UpdateAccountParamsExecutionRegion | Unset + if isinstance(_execution_region, Unset): + execution_region = UNSET + else: + execution_region = UpdateAccountParamsExecutionRegion(_execution_region) + is_self_hosted_only = d.pop("is_self_hosted_only", UNSET) name = d.pop("name", UNSET) update_account_params = cls( schema=schema, + execution_region=execution_region, is_self_hosted_only=is_self_hosted_only, name=name, ) diff --git a/src/tower/tower_api_client/models/update_account_params_execution_region.py b/src/tower/tower_api_client/models/update_account_params_execution_region.py new file mode 100644 index 00000000..0e5e7047 --- /dev/null +++ b/src/tower/tower_api_client/models/update_account_params_execution_region.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class UpdateAccountParamsExecutionRegion(str, Enum): + EU_CENTRAL_1 = "eu-central-1" + US_EAST_1 = "us-east-1" + + def __str__(self) -> str: + return str(self.value) diff --git a/src/tower/tower_api_client/models/update_app_params.py b/src/tower/tower_api_client/models/update_app_params.py index 98fbac83..c970dfd0 100644 --- a/src/tower/tower_api_client/models/update_app_params.py +++ b/src/tower/tower_api_client/models/update_app_params.py @@ -1,12 +1,16 @@ from __future__ import annotations from collections.abc import Mapping -from typing import Any, TypeVar, cast +from typing import TYPE_CHECKING, Any, TypeVar, cast from attrs import define as _attrs_define from ..types import UNSET, Unset +if TYPE_CHECKING: + from ..models.run_retry_policy import RunRetryPolicy + + T = TypeVar("T", bound="UpdateAppParams") @@ -21,6 +25,7 @@ class UpdateAppParams: its runs should get a hostname assigned to it. pending_timeout (int | None | Unset): The amount of time in seconds that runs of this app can stay in pending state before being marked as failed. + retry_policy (RunRetryPolicy | Unset): running_timeout (int | None | Unset): The amount of time in seconds that runs of this app can stay in running state before being marked as failed. status (None | str | Unset): New status for the App @@ -32,6 +37,7 @@ class UpdateAppParams: description: None | str | Unset = UNSET is_externally_accessible: bool | None | Unset = UNSET pending_timeout: int | None | Unset = UNSET + retry_policy: RunRetryPolicy | Unset = UNSET running_timeout: int | None | Unset = UNSET status: None | str | Unset = UNSET subdomain: None | str | Unset = UNSET @@ -57,6 +63,10 @@ def to_dict(self) -> dict[str, Any]: else: pending_timeout = self.pending_timeout + retry_policy: dict[str, Any] | Unset = UNSET + if not isinstance(self.retry_policy, Unset): + retry_policy = self.retry_policy.to_dict() + running_timeout: int | None | Unset if isinstance(self.running_timeout, Unset): running_timeout = UNSET @@ -86,6 +96,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["is_externally_accessible"] = is_externally_accessible if pending_timeout is not UNSET: field_dict["pending_timeout"] = pending_timeout + if retry_policy is not UNSET: + field_dict["retry_policy"] = retry_policy if running_timeout is not UNSET: field_dict["running_timeout"] = running_timeout if status is not UNSET: @@ -97,6 +109,8 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.run_retry_policy import RunRetryPolicy + d = dict(src_dict) schema = d.pop("$schema", UNSET) @@ -129,6 +143,13 @@ def _parse_pending_timeout(data: object) -> int | None | Unset: pending_timeout = _parse_pending_timeout(d.pop("pending_timeout", UNSET)) + _retry_policy = d.pop("retry_policy", UNSET) + retry_policy: RunRetryPolicy | Unset + if isinstance(_retry_policy, Unset): + retry_policy = UNSET + else: + retry_policy = RunRetryPolicy.from_dict(_retry_policy) + def _parse_running_timeout(data: object) -> int | None | Unset: if data is None: return data @@ -161,6 +182,7 @@ def _parse_subdomain(data: object) -> None | str | Unset: description=description, is_externally_accessible=is_externally_accessible, pending_timeout=pending_timeout, + retry_policy=retry_policy, running_timeout=running_timeout, status=status, subdomain=subdomain, diff --git a/src/tower/tower_api_client/models/update_schedule_params.py b/src/tower/tower_api_client/models/update_schedule_params.py index 1d891105..23a80a7e 100644 --- a/src/tower/tower_api_client/models/update_schedule_params.py +++ b/src/tower/tower_api_client/models/update_schedule_params.py @@ -22,31 +22,31 @@ class UpdateScheduleParams: """ Attributes: - name (None | str): The name for this schedule. Must be unique per team. schema (str | Unset): A URL to the JSON Schema for this object. Example: https://api.tower.dev/v1/schemas/UpdateScheduleParams.json. app_version (None | str | Unset): The specific app version to run (if omitted, will use the app's default version) cron (str | Unset): The cron expression defining when the app should run environment (str | Unset): The environment to run the app in Default: 'default'. + name (None | str | Unset): The name for this schedule. Must be unique per team. overlap_policy (UpdateScheduleParamsOverlapPolicy | Unset): The overlap policy for the schedule parameters (list[RunParameter] | Unset): Parameters to pass when running the app status (UpdateScheduleParamsStatus | Unset): The status of the schedule + timezone (None | str | Unset): The IANA timezone identifier that the cron expression should be evaluated in + (e.g., 'America/New_York', 'Europe/London'). """ - name: None | str schema: str | Unset = UNSET app_version: None | str | Unset = UNSET cron: str | Unset = UNSET environment: str | Unset = "default" + name: None | str | Unset = UNSET overlap_policy: UpdateScheduleParamsOverlapPolicy | Unset = UNSET parameters: list[RunParameter] | Unset = UNSET status: UpdateScheduleParamsStatus | Unset = UNSET + timezone: None | str | Unset = UNSET def to_dict(self) -> dict[str, Any]: - name: None | str - name = self.name - schema = self.schema app_version: None | str | Unset @@ -59,6 +59,12 @@ def to_dict(self) -> dict[str, Any]: environment = self.environment + name: None | str | Unset + if isinstance(self.name, Unset): + name = UNSET + else: + name = self.name + overlap_policy: str | Unset = UNSET if not isinstance(self.overlap_policy, Unset): overlap_policy = self.overlap_policy.value @@ -74,13 +80,15 @@ def to_dict(self) -> dict[str, Any]: if not isinstance(self.status, Unset): status = self.status.value + timezone: None | str | Unset + if isinstance(self.timezone, Unset): + timezone = UNSET + else: + timezone = self.timezone + field_dict: dict[str, Any] = {} - field_dict.update( - { - "name": name, - } - ) + field_dict.update({}) if schema is not UNSET: field_dict["$schema"] = schema if app_version is not UNSET: @@ -89,12 +97,16 @@ def to_dict(self) -> dict[str, Any]: field_dict["cron"] = cron if environment is not UNSET: field_dict["environment"] = environment + if name is not UNSET: + field_dict["name"] = name if overlap_policy is not UNSET: field_dict["overlap_policy"] = overlap_policy if parameters is not UNSET: field_dict["parameters"] = parameters if status is not UNSET: field_dict["status"] = status + if timezone is not UNSET: + field_dict["timezone"] = timezone return field_dict @@ -103,14 +115,6 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.run_parameter import RunParameter d = dict(src_dict) - - def _parse_name(data: object) -> None | str: - if data is None: - return data - return cast(None | str, data) - - name = _parse_name(d.pop("name")) - schema = d.pop("$schema", UNSET) def _parse_app_version(data: object) -> None | str | Unset: @@ -126,6 +130,15 @@ def _parse_app_version(data: object) -> None | str | Unset: environment = d.pop("environment", UNSET) + def _parse_name(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + name = _parse_name(d.pop("name", UNSET)) + _overlap_policy = d.pop("overlap_policy", UNSET) overlap_policy: UpdateScheduleParamsOverlapPolicy | Unset if isinstance(_overlap_policy, Unset): @@ -149,15 +162,25 @@ def _parse_app_version(data: object) -> None | str | Unset: else: status = UpdateScheduleParamsStatus(_status) + def _parse_timezone(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + timezone = _parse_timezone(d.pop("timezone", UNSET)) + update_schedule_params = cls( - name=name, schema=schema, app_version=app_version, cron=cron, environment=environment, + name=name, overlap_policy=overlap_policy, parameters=parameters, status=status, + timezone=timezone, ) return update_schedule_params diff --git a/src/tower/tower_api_client/models/update_team_params.py b/src/tower/tower_api_client/models/update_team_params.py index 310819f3..83392ef6 100644 --- a/src/tower/tower_api_client/models/update_team_params.py +++ b/src/tower/tower_api_client/models/update_team_params.py @@ -5,6 +5,7 @@ from attrs import define as _attrs_define +from ..models.update_team_params_execution_region import UpdateTeamParamsExecutionRegion from ..types import UNSET, Unset T = TypeVar("T", bound="UpdateTeamParams") @@ -18,10 +19,13 @@ class UpdateTeamParams: team name. schema (str | Unset): A URL to the JSON Schema for this object. Example: https://api.tower.dev/v1/schemas/UpdateTeamParams.json. + execution_region (UpdateTeamParamsExecutionRegion | Unset): The execution region for runs (eu-central-1 or us- + east-1) """ name: None | str schema: str | Unset = UNSET + execution_region: UpdateTeamParamsExecutionRegion | Unset = UNSET def to_dict(self) -> dict[str, Any]: name: None | str @@ -29,6 +33,10 @@ def to_dict(self) -> dict[str, Any]: schema = self.schema + execution_region: str | Unset = UNSET + if not isinstance(self.execution_region, Unset): + execution_region = self.execution_region.value + field_dict: dict[str, Any] = {} field_dict.update( @@ -38,6 +46,8 @@ def to_dict(self) -> dict[str, Any]: ) if schema is not UNSET: field_dict["$schema"] = schema + if execution_region is not UNSET: + field_dict["execution_region"] = execution_region return field_dict @@ -54,9 +64,17 @@ def _parse_name(data: object) -> None | str: schema = d.pop("$schema", UNSET) + _execution_region = d.pop("execution_region", UNSET) + execution_region: UpdateTeamParamsExecutionRegion | Unset + if isinstance(_execution_region, Unset): + execution_region = UNSET + else: + execution_region = UpdateTeamParamsExecutionRegion(_execution_region) + update_team_params = cls( name=name, schema=schema, + execution_region=execution_region, ) return update_team_params diff --git a/src/tower/tower_api_client/models/update_team_params_execution_region.py b/src/tower/tower_api_client/models/update_team_params_execution_region.py new file mode 100644 index 00000000..8d3f524d --- /dev/null +++ b/src/tower/tower_api_client/models/update_team_params_execution_region.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class UpdateTeamParamsExecutionRegion(str, Enum): + EU_CENTRAL_1 = "eu-central-1" + US_EAST_1 = "us-east-1" + + def __str__(self) -> str: + return str(self.value) diff --git a/src/tower/tower_api_client/models/usage_limit.py b/src/tower/tower_api_client/models/usage_limit.py new file mode 100644 index 00000000..e3503dcf --- /dev/null +++ b/src/tower/tower_api_client/models/usage_limit.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define + +T = TypeVar("T", bound="UsageLimit") + + +@_attrs_define +class UsageLimit: + """ + Attributes: + limit (int): For numeric quotas: the maximum number of units allowed (-1 means unlimited). For boolean + entitlements (e.g. self_hosted_runners): 0 = disabled, 1 = enabled. + used (int): The number of units used for this resource. + """ + + limit: int + used: int + + def to_dict(self) -> dict[str, Any]: + limit = self.limit + + used = self.used + + field_dict: dict[str, Any] = {} + + field_dict.update( + { + "limit": limit, + "used": used, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + limit = d.pop("limit") + + used = d.pop("used") + + usage_limit = cls( + limit=limit, + used=used, + ) + + return usage_limit diff --git a/tests/integration/features/cli_api_key_auth.feature b/tests/integration/features/cli_api_key_auth.feature new file mode 100644 index 00000000..c559c819 --- /dev/null +++ b/tests/integration/features/cli_api_key_auth.feature @@ -0,0 +1,18 @@ +Feature: API Key Authentication + As a user authenticating with an API key + I want the CLI to use the X-API-Key header + So that I can interact with Tower without a session + + Scenario: List apps using API key auth + When I run "tower --json apps list" via CLI with API key + Then the output should be valid JSON + And no session.json should exist in the temp home + + Scenario: List teams using API key auth + When I run "tower teams list" via CLI with API key + Then no session.json should exist in the temp home + + Scenario: Login warns when API key is set + When I run "tower login --no-browser" via CLI with API key + Then the output should show "TOWER_API_KEY is set" + And the output should show "ignore the session" diff --git a/tests/integration/features/steps/cli_steps.py b/tests/integration/features/steps/cli_steps.py index e0b71da6..fb6d463f 100644 --- a/tests/integration/features/steps/cli_steps.py +++ b/tests/integration/features/steps/cli_steps.py @@ -57,6 +57,54 @@ def step_run_cli_command(context, command): raise +@step('I run "{command}" via CLI with API key') +def step_run_cli_command_with_api_key(context, command): + """Run a Tower CLI command authenticating via TOWER_API_KEY instead of session.json""" + cli_path = context.tower_binary + + cmd_parts = shlex.split(command) + full_command = [cli_path] + cmd_parts[1:] # Skip 'tower' prefix + + try: + test_env = os.environ.copy() + test_env["FORCE_COLOR"] = "1" + test_env["CLICOLOR_FORCE"] = "1" + test_env["TOWER_URL"] = context.tower_url + test_env["TOWER_API_KEY"] = "sk-test-api-key" + + # Use a temp HOME with no session.json to prove API key auth works standalone + test_env["HOME"] = context.temp_dir + + result = subprocess.run( + full_command, + capture_output=True, + text=True, + timeout=60, + env=test_env, + ) + context.cli_output = result.stdout + result.stderr + context.cli_stdout = result.stdout + context.cli_return_code = result.returncode + except subprocess.TimeoutExpired: + context.cli_output = "Command timed out" + context.cli_stdout = "" + context.cli_return_code = 124 + except Exception as e: + print(f"DEBUG: Exception in CLI command: {type(e).__name__}: {e}") + print(f"DEBUG: Command was: {full_command}") + print(f"DEBUG: Working directory: {os.getcwd()}") + raise + + +@step("no session.json should exist in the temp home") +def step_no_session_json(context): + """Verify that API key auth did not create a session.json file""" + session_path = Path(context.temp_dir) / ".config" / "tower" / "session.json" + assert ( + not session_path.exists() + ), f"session.json should not exist but found at {session_path}" + + @step('I run "{command}" via CLI using created app name') def step_run_cli_command_with_app_name(context, command): """Run a Tower CLI command with the generated app name injected.""" @@ -266,12 +314,12 @@ def step_output_should_show_header_in_green_bold(context, header): @step("the table headers should be yellow colored") def step_table_headers_should_be_yellow(context): - """Verify table headers appear in yellow""" + """Verify table headers appear in bold yellow""" output = context.cli_output - yellow_code = "\x1b[33m" # Yellow text + yellow_bold_code = "\x1b[1;33m" assert ( - yellow_code in output - ), f"Expected yellow color codes in table headers, got: {output}" + yellow_bold_code in output + ), f"Expected bold yellow color codes in table headers, got: {output}" @step('the table should show columns "{column_list}"') diff --git a/tests/mock-api-server/main.py b/tests/mock-api-server/main.py index b8ea7762..7faff7d0 100644 --- a/tests/mock-api-server/main.py +++ b/tests/mock-api-server/main.py @@ -67,6 +67,7 @@ async def log_requests(request: Request, call_next): "errored": 0, "exited": 0, "pending": 0, + "retrying": 0, "running": 0, }, "subdomain": None, @@ -96,6 +97,7 @@ def create_schedule_object( "environment": environment, "overlap_policy": "skip", "status": "active", + "timezone": "UTC", "created_at": now_iso(), "updated_at": now_iso(), "parameters": parameters or [], @@ -156,6 +158,7 @@ async def create_app(app_data: Dict[str, Any]): "errored": 0, "exited": 0, "pending": 0, + "retrying": 0, "running": 0, }, "schedule": None, @@ -283,6 +286,7 @@ async def run_app(name: str, run_params: Dict[str, Any]): "started_at": datetime.datetime.now().isoformat(), "ended_at": None, "app_version": mock_apps_db[name].get("version", "1.0.0"), + "num_attempts": 1, "subdomain": None, "is_scheduled": True, "initiator": { @@ -328,7 +332,9 @@ async def describe_run(name: str, seq: int): "run": run_data, "$links": { "next": None, + "next_number": None, "prev": None, + "prev_number": None, "self": run_data.get("$link"), }, } @@ -542,6 +548,7 @@ async def refresh_session(refresh_params: Dict[str, Any] = None): def make_log_data(seq: int, line_num: int, content: str, timestamp: str): return { + "attempt_seq": 1, "channel": "program", "content": content, "line_num": line_num, diff --git a/tests/tower/test_client.py b/tests/tower/test_client.py index 78b04f34..beb48cc7 100644 --- a/tests/tower/test_client.py +++ b/tests/tower/test_client.py @@ -54,13 +54,16 @@ def _create_run_response( "status": status, "exit_code": None, "status_group": status_group, + "num_attempts": 1, "parameters": parameters, "initiator": {"type": "tower_cli", "details": {}}, "is_scheduled": False, }, "$links": { "next": None, + "next_number": None, "prev": None, + "prev_number": None, "self": f"https://api.example.com/v1/apps/my-app/runs/{number}", }, } @@ -93,6 +96,7 @@ def _create_run( created_at="2025-04-25T20:54:58.762547Z", ended_at="2025-04-25T20:55:35.220295Z", environment="default", + num_attempts=1, number=number, run_id=run_id, scheduled_at="2025-04-25T20:54:58.761867Z", diff --git a/uv.lock b/uv.lock index 698ef9ea..7c4d3db5 100644 --- a/uv.lock +++ b/uv.lock @@ -656,6 +656,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7d/ed/6bfa4109fcb23a58819600392564fea69cdc6551ffd5e69ccf1d52a40cbc/greenlet-3.2.4-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c", size = 271061, upload-time = "2025-08-07T13:17:15.373Z" }, { url = "https://files.pythonhosted.org/packages/2a/fc/102ec1a2fc015b3a7652abab7acf3541d58c04d3d17a8d3d6a44adae1eb1/greenlet-3.2.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590", size = 629475, upload-time = "2025-08-07T13:42:54.009Z" }, { url = "https://files.pythonhosted.org/packages/c5/26/80383131d55a4ac0fb08d71660fd77e7660b9db6bdb4e8884f46d9f2cc04/greenlet-3.2.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c", size = 640802, upload-time = "2025-08-07T13:45:25.52Z" }, + { url = "https://files.pythonhosted.org/packages/9f/7c/e7833dbcd8f376f3326bd728c845d31dcde4c84268d3921afcae77d90d08/greenlet-3.2.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c8c9e331e58180d0d83c5b7999255721b725913ff6bc6cf39fa2a45841a4fd4b", size = 636703, upload-time = "2025-08-07T13:53:12.622Z" }, { url = "https://files.pythonhosted.org/packages/e9/49/547b93b7c0428ede7b3f309bc965986874759f7d89e4e04aeddbc9699acb/greenlet-3.2.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31", size = 635417, upload-time = "2025-08-07T13:18:25.189Z" }, { url = "https://files.pythonhosted.org/packages/7f/91/ae2eb6b7979e2f9b035a9f612cf70f1bf54aad4e1d125129bef1eae96f19/greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d", size = 584358, upload-time = "2025-08-07T13:18:23.708Z" }, { url = "https://files.pythonhosted.org/packages/f7/85/433de0c9c0252b22b16d413c9407e6cb3b41df7389afc366ca204dbc1393/greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5", size = 1113550, upload-time = "2025-08-07T13:42:37.467Z" }, @@ -666,6 +667,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5e/405965351aef8c76b8ef7ad370e5da58d57ef6068df197548b015464001a/greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633", size = 640519, upload-time = "2025-08-07T13:53:13.928Z" }, { url = "https://files.pythonhosted.org/packages/25/5d/382753b52006ce0218297ec1b628e048c4e64b155379331f25a7316eb749/greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079", size = 639707, upload-time = "2025-08-07T13:18:27.146Z" }, { url = "https://files.pythonhosted.org/packages/1f/8e/abdd3f14d735b2929290a018ecf133c901be4874b858dd1c604b9319f064/greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8", size = 587684, upload-time = "2025-08-07T13:18:25.164Z" }, { url = "https://files.pythonhosted.org/packages/5d/65/deb2a69c3e5996439b0176f6651e0052542bb6c8f8ec2e3fba97c9768805/greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52", size = 1116647, upload-time = "2025-08-07T13:42:38.655Z" }, @@ -676,6 +678,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/44/69/9b804adb5fd0671f367781560eb5eb586c4d495277c93bde4307b9e28068/greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd", size = 274079, upload-time = "2025-08-07T13:15:45.033Z" }, { url = "https://files.pythonhosted.org/packages/46/e9/d2a80c99f19a153eff70bc451ab78615583b8dac0754cfb942223d2c1a0d/greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb", size = 640997, upload-time = "2025-08-07T13:42:56.234Z" }, { url = "https://files.pythonhosted.org/packages/3b/16/035dcfcc48715ccd345f3a93183267167cdd162ad123cd93067d86f27ce4/greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968", size = 655185, upload-time = "2025-08-07T13:45:27.624Z" }, + { url = "https://files.pythonhosted.org/packages/31/da/0386695eef69ffae1ad726881571dfe28b41970173947e7c558d9998de0f/greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9", size = 649926, upload-time = "2025-08-07T13:53:15.251Z" }, { url = "https://files.pythonhosted.org/packages/68/88/69bf19fd4dc19981928ceacbc5fd4bb6bc2215d53199e367832e98d1d8fe/greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6", size = 651839, upload-time = "2025-08-07T13:18:30.281Z" }, { url = "https://files.pythonhosted.org/packages/19/0d/6660d55f7373b2ff8152401a83e02084956da23ae58cddbfb0b330978fe9/greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0", size = 607586, upload-time = "2025-08-07T13:18:28.544Z" }, { url = "https://files.pythonhosted.org/packages/8e/1a/c953fdedd22d81ee4629afbb38d2f9d71e37d23caace44775a3a969147d4/greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0", size = 1123281, upload-time = "2025-08-07T13:42:39.858Z" }, @@ -686,6 +689,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/49/e8/58c7f85958bda41dafea50497cbd59738c5c43dbbea5ee83d651234398f4/greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31", size = 272814, upload-time = "2025-08-07T13:15:50.011Z" }, { url = "https://files.pythonhosted.org/packages/62/dd/b9f59862e9e257a16e4e610480cfffd29e3fae018a68c2332090b53aac3d/greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945", size = 641073, upload-time = "2025-08-07T13:42:57.23Z" }, { url = "https://files.pythonhosted.org/packages/f7/0b/bc13f787394920b23073ca3b6c4a7a21396301ed75a655bcb47196b50e6e/greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc", size = 655191, upload-time = "2025-08-07T13:45:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d6/6adde57d1345a8d0f14d31e4ab9c23cfe8e2cd39c3baf7674b4b0338d266/greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a", size = 649516, upload-time = "2025-08-07T13:53:16.314Z" }, { url = "https://files.pythonhosted.org/packages/7f/3b/3a3328a788d4a473889a2d403199932be55b1b0060f4ddd96ee7cdfcad10/greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504", size = 652169, upload-time = "2025-08-07T13:18:32.861Z" }, { url = "https://files.pythonhosted.org/packages/ee/43/3cecdc0349359e1a527cbf2e3e28e5f8f06d3343aaf82ca13437a9aa290f/greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671", size = 610497, upload-time = "2025-08-07T13:18:31.636Z" }, { url = "https://files.pythonhosted.org/packages/b8/19/06b6cf5d604e2c382a6f31cafafd6f33d5dea706f4db7bdab184bad2b21d/greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b", size = 1121662, upload-time = "2025-08-07T13:42:41.117Z" }, @@ -696,6 +700,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/5c/85273fd7cc388285632b0498dbbab97596e04b154933dfe0f3e68156c68c/greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0", size = 273586, upload-time = "2025-08-07T13:16:08.004Z" }, { url = "https://files.pythonhosted.org/packages/d1/75/10aeeaa3da9332c2e761e4c50d4c3556c21113ee3f0afa2cf5769946f7a3/greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f", size = 686346, upload-time = "2025-08-07T13:42:59.944Z" }, { url = "https://files.pythonhosted.org/packages/c0/aa/687d6b12ffb505a4447567d1f3abea23bd20e73a5bed63871178e0831b7a/greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5", size = 699218, upload-time = "2025-08-07T13:45:30.969Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8b/29aae55436521f1d6f8ff4e12fb676f3400de7fcf27fccd1d4d17fd8fecd/greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1", size = 694659, upload-time = "2025-08-07T13:53:17.759Z" }, { url = "https://files.pythonhosted.org/packages/92/2e/ea25914b1ebfde93b6fc4ff46d6864564fba59024e928bdc7de475affc25/greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735", size = 695355, upload-time = "2025-08-07T13:18:34.517Z" }, { url = "https://files.pythonhosted.org/packages/72/60/fc56c62046ec17f6b0d3060564562c64c862948c9d4bc8aa807cf5bd74f4/greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337", size = 657512, upload-time = "2025-08-07T13:18:33.969Z" }, { url = "https://files.pythonhosted.org/packages/23/6e/74407aed965a4ab6ddd93a7ded3180b730d281c77b765788419484cdfeef/greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269", size = 1612508, upload-time = "2025-11-04T12:42:23.427Z" }, @@ -2483,7 +2488,7 @@ wheels = [ [[package]] name = "tower" -version = "0.3.55" +version = "0.3.56" source = { editable = "." } dependencies = [ { name = "attrs" },