Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add apps subcommand that allows to list and delete apps #67

Merged
merged 1 commit into from
Aug 23, 2023

Conversation

karthik2804
Copy link
Collaborator

This PR adds a new top-level command apps that further has list and delete subcommands.

fixes #9
fixes #40

src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/mod.rs Show resolved Hide resolved
@karthik2804 karthik2804 force-pushed the subcommand/apps branch 2 times, most recently from 4ea8eb7 to abb0530 Compare August 18, 2023 21:48
src/commands/apps.rs Outdated Show resolved Hide resolved
let mut app_list_page = client.list_apps(DEFAULT_APPLIST_PAGE_SIZE, None).await?;
match (app_list_page.is_last_page, cmd.all) {
(true, _) | (false, true) => println!("Apps ({})", app_list_page.total_items),
(false, false) => println!("Note: Displaying the first {} of {} Apps. To list all the apps run \"spin cloud apps list -all\"", DEFAULT_APPLIST_PAGE_SIZE, app_list_page.total_items),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"all" should be the default (if not the only option). Showing one page is effectively giving the user a random subset, which doesn't seem terribly useful, or am I missing something? I guess maybe if all they care about is the count...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like making it the default option - I will add an option called count that returns the total number of apps.

src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/deploy.rs Outdated Show resolved Hide resolved
@@ -404,7 +404,7 @@ impl DeployCommand {
cloud_client: &CloudClient,
name: String,
) -> Result<Option<Uuid>> {
let apps_vm = CloudClient::list_apps(cloud_client).await?;
let apps_vm = CloudClient::list_apps(cloud_client, 50, None).await?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe out of scope but it feels like this should page too - what is the app is not in the first page?

@@ -230,7 +231,7 @@ impl LoginCommand {
insecure: self.insecure,
token: token.clone(),
})
.list_apps()
.list_apps(DEFAULT_APPLIST_PAGE_SIZE, None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe out of scope, but I believe the page size here could be 1 (since this is just to verify that the creds work, not to actually list any apps).

@@ -19,10 +20,21 @@ pub(crate) async fn create_cloud_client(deployment_env_id: Option<&str>) -> Resu
}

pub(crate) async fn get_app_id_cloud(cloud_client: &CloudClient, name: &str) -> Result<Uuid> {
let apps_vm = CloudClient::list_apps(cloud_client).await?;
let apps_vm = CloudClient::list_apps(cloud_client, DEFAULT_APPLIST_PAGE_SIZE, None).await?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this needs to page (but may be out of scope for this PR)

api_apps_get(&self.configuration, None, None, None, None, None, None)
.await
.map_err(format_response_error)
pub async fn list_apps(&self, page_size: i32, page_index: Option<i32>) -> Result<AppItemPage> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

page_size and page_index should really be unsigned at the Rust level even if .NET advertises it as signed. (But I get this runs into issues about "what if somebody asks for 2^31 + 1 items how do you convert that Ivan".)

src/commands/apps.rs Outdated Show resolved Hide resolved
@karthik2804 karthik2804 force-pushed the subcommand/apps branch 2 times, most recently from a0ba904 to 737242a Compare August 21, 2023 15:59
Copy link
Contributor

@itowlson itowlson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only blocker is the incorrect syntax for the count flag, but I think we should also make sure we have consensus on the UI e.g. whether we want to have the count flag, whether we want to have a header row, and whether we want to print anything when there are no entities. This is important because of likely broader implications e.g. we'd probably want the sqlite list command to have the same behaviour.

src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/apps.rs Show resolved Hide resolved
AppsCommand::List(cmd) => {
let client = create_cloud_client(cmd.common.deployment_env_id.as_deref()).await?;
let mut app_list_page = client.list_apps(DEFAULT_APPLIST_PAGE_SIZE, None).await?;
match app_list_page.total_items > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, why did you choose to do a match statement here instead of an if statement?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Past reviews have trained me to prefer match over if but I do not know if it is not appropriate here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would usually only match on a bool if it was evaluating to a result that the match was capturing. I'm curious if there is a best practice here. @itowlson any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a predicate like this I'd probably choose if because it avoids the clutter of the true => / false => prefixes (but my opinion is not strong, and I am a really poor bellwether for what the Rust Gods consider best practice).

Copy link
Collaborator

@kate-goldenring kate-goldenring left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is looking ready to switch from Draft to Ready for Review. To your comment @itowlson, I am aligned with no headers and instead output on empty as is done here.

src/commands/apps.rs Outdated Show resolved Hide resolved
src/commands/apps.rs Outdated Show resolved Hide resolved
@karthik2804 karthik2804 marked this pull request as ready for review August 22, 2023 18:07
Copy link
Contributor

@itowlson itowlson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, one non-blocking suggestion (plus the comment about if vs match which is also non-blocking)

impl AppsCommand {
pub async fn run(self) -> Result<()> {
match self {
AppsCommand::List(cmd) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style suggestion: In many places we move each leaf command's run implementation down to that leaf command, so the intermediate level becomes (cf. https://github.com/fermyon/spin/blob/60011faf310e673f20fc7d5de20f4df8a99374e7/src/commands/plugins.rs#L43)

impl FieCommand {
  fn run(&self) {
    match self {
      Self::AliceCommand(cmd) => cmd.run(),
      Self::BobCommand(cmd) => cmd.run(),
    }
  }
}

This removes a level of structure and indentation from the actual real command logic, and keeps the implementations of the subcommands fully distinct in the source code.

It's not a must-do but it's a pattern I find significantly clearer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I based it off the structure in variables and sqlite. I do not have a preference here. I am happy to go eitherway. Let me know!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, if cloud-plugin is inlining everything then I guess be consistent.

@karthik2804
Copy link
Collaborator Author

@kate-goldenring @itowlson any strong opinions on match vs if? I am happy to go either way. I can update and then merge.

@itowlson
Copy link
Contributor

@karthik2804 I am Team If in this case

Signed-off-by: karthik2804 <karthik.ganeshram@fermyon.com>
@karthik2804
Copy link
Collaborator Author

@itowlson Well I will take the side with Team if this time around then!

@itowlson
Copy link
Contributor

image

@karthik2804 karthik2804 merged commit 50535f7 into fermyon:main Aug 23, 2023
8 checks passed
@karthik2804 karthik2804 deleted the subcommand/apps branch August 23, 2023 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Spin CLI should allow me to remove a deployment Support listing all application in the cloud
3 participants