Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 89 additions & 3 deletions rust/src/application/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,10 @@ fn update_command() -> RuntimeCommandSpec {
RuntimeCommandSpec::new_with_context(
CommandSpec::new("update", "Update an application")
.with_long(
"Update the label or description of a GoDaddy developer-platform application \
by its ID. At least one of --label or --description must be provided. \
Use `application info --name <name>` to retrieve the application ID.",
"Update the label, description, or status of a GoDaddy developer-platform \
application by its ID. At least one of --label, --description, or --status \
must be provided. Use `application info --name <name>` to retrieve the \
application ID.",
)
.with_system("applications")
.with_tier(Tier::Mutate)
Expand All @@ -474,13 +475,24 @@ fn update_command() -> RuntimeCommandSpec {
clap::Arg::new("label")
.long("label")
.value_name("LABEL")
// CommandSpec has no ArgGroup; this enforces "at least one" at parse time.
.required_unless_present_any(["description", "status"])
.help("New label"),
)
.with_arg(
clap::Arg::new("description")
.long("description")
.value_name("TEXT")
.required_unless_present_any(["label", "status"])
.help("New description"),
)
.with_arg(
clap::Arg::new("status")
.long("status")
.value_name("STATUS")
.value_parser(["ACTIVE", "INACTIVE"])
.required_unless_present_any(["label", "description"])
.help("Application status (ACTIVE or INACTIVE)"),
),
Comment thread
qcai-godaddy marked this conversation as resolved.
|ctx| async move {
let id = arg_str(&ctx, "id").to_owned();
Expand All @@ -491,6 +503,9 @@ fn update_command() -> RuntimeCommandSpec {
if let Some(desc) = ctx.args.get("description").and_then(|v| v.as_str()) {
input.insert("description".to_owned(), json!(desc));
}
if let Some(status) = ctx.args.get("status").and_then(|v| v.as_str()) {
input.insert("status".to_owned(), json!(status));
}
let client = make_client(&ctx).await?;
let data = client
.update_application(&id, json!(input))
Expand Down Expand Up @@ -1504,6 +1519,77 @@ pub fn add_extension_group() -> RuntimeGroupSpec {
mod tests {
use cli_engine::{Cli, CliConfig, Stage};

use super::update_command;

fn update_clap_command() -> clap::Command {
update_command().spec.clap_command()
}

#[test]
fn status_rejects_values_outside_active_inactive() {
for bad in ["active", "DISABLED", "PENDING"] {
let err = update_clap_command()
.try_get_matches_from(["update", "--id", "app-1", "--status", bad])
.expect_err("invalid --status should be rejected");
assert_eq!(
err.kind(),
clap::error::ErrorKind::InvalidValue,
"--status {bad:?} should fail possible-value validation, got: {err}"
);
}
}

#[test]
fn status_accepts_active_and_inactive() {
for good in ["ACTIVE", "INACTIVE"] {
update_clap_command()
.try_get_matches_from(["update", "--id", "app-1", "--status", good])
.expect("ACTIVE|INACTIVE --status should be accepted");
}
}

#[test]
fn update_requires_at_least_one_field() {
let err = update_clap_command()
.try_get_matches_from(["update", "--id", "app-1"])
.expect_err("update with only --id should be rejected at parse time");
assert_eq!(
err.kind(),
clap::error::ErrorKind::MissingRequiredArgument,
"expected MissingRequiredArgument, got: {err}"
);
}

#[test]
fn update_accepts_any_single_field() {
update_clap_command()
.try_get_matches_from(["update", "--id", "app-1", "--label", "New"])
.expect("--label alone should be accepted");
update_clap_command()
.try_get_matches_from(["update", "--id", "app-1", "--description", "Desc"])
.expect("--description alone should be accepted");
update_clap_command()
.try_get_matches_from(["update", "--id", "app-1", "--status", "ACTIVE"])
.expect("--status alone should be accepted");
}

#[test]
fn update_accepts_multiple_fields() {
update_clap_command()
.try_get_matches_from([
"update",
"--id",
"app-1",
"--label",
"New",
"--description",
"Desc",
"--status",
"INACTIVE",
])
.expect("multiple update fields should be allowed together");
}

/// API commands must stay fail-closed: `application list` calls the backend,
/// so it must require authentication. Built with **no auth provider
/// registered**, the engine's default `AuthRequirement::Required` must reject
Expand Down