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

Phil/flowctl subcomands #360

Merged
merged 7 commits into from Feb 9, 2022
Merged

Phil/flowctl subcomands #360

merged 7 commits into from Feb 9, 2022

Conversation

psFried
Copy link
Member

@psFried psFried commented Feb 7, 2022

Description:

Adds the flowctl-rs binary, which delegates to the current flowctl Go binary for most subcommands. The eventual goal is to have this binary replace the existing flowctl as the main entrypoint for users to interact with the CLI. For now, it simply delegates a bunch of subcommands to the existing flowctl binary, and also integrates a few rust-based internal subcommands.

Workflow steps:

After a make package, there will be a new binary at .build/package/bin/flowctl-rs. This binary should be a drop-in replacement for flowctl and everything should work exactly the same, except for the name of the executable. The intent is to let it bake a little as flowctl-rs before renaming it to replace the go-based flowctl

Documentation links affected:

There's no user-facing impact at this stage, and the plan is to keep it that way.

Notes for reviewers:

Reviewing commit by commit is probably best, though there are a few refactors along the way.


This change is Reviewable

This includes execution of first-party external subcomands. There are
not yet any internal subcommands.
Sets up a basic rust crate that all of our rust-based CLIs can use for
initializing logging and doing other cli-ish things consistently.
This was chosen as a good first target for porting over a subcommand
from the Go-based flowctl to the new rust-based flowctl-rs because it's
fairly simple, non-essential, and doesn't rely on any Go packages.
This is intended to prove out how both internal and external subcomands
can co-exist within flowctl-rs.
- Migrate schemalate from separate binaries to internal subcommands.
- Handle --version in flowctl-rs, which is determined in Makefile and
  passed as the `FLOW_VERSION` environment variable.
- Remove usages of `or_bail` in the combine subcommand, in favor of just
  returning an error. The rationale being that using `or_bail` would
  make composition of subcommands needlessly painful.
Copy link
Contributor

@saterus saterus left a comment

Choose a reason for hiding this comment

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

This looks good to me. I pulled it down and played around with the CLI. Seems to work exactly as expected for both Rust internal commands and Go external commands.

Comment on lines +6 to +9
# This just provides a default value for FLOW_VERSION during development, so that you can compile
# without this being set. If FLOW_VERSION is defined, then this has no effect.
[env]
FLOW_VERSION = "dev"
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't know about this. Super handy. 💯

Comment on lines +12 to +15
/// Helper trait for exiting the application early if there's an error.
pub trait OrBail<T> {
fn or_bail(self, message: &str) -> T;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This was in flux a bit, but does not appear to be in use anymore. Do we want to keep it around for later usage, or is it something we want to discourage now?

Copy link
Member Author

Choose a reason for hiding this comment

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

TBH, I'm thinking we should discourage its use in favor of just returning a Result<(), anyhow::Error>. I figured I'd keep it around temporarily in case any of the other CLIs use it. I think I'll be able to delete it pretty quickly, though.

[package]
name = "flowctl"
version = "0.1.0"
edition = "2021"
Copy link
Contributor

Choose a reason for hiding this comment

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

General question beyond this PR: what's our minimum Rust target? I ran into trouble locally because I was still running 1.55 and 2021 Edition was stabilized in 1.56. It was easy to fix, but figured I'd ask. The CI Dockerfile installs 1.57.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think we've ever really taken a position on that. I think everyone's always just defaulted to installing a relatively recent version and upgrading whenever we want to use new rust features. IMO that's probably fine for now, since nobody outside of us is really depending on our crates as libraries.

#[clap(long, default_value = ".")]
pub directory: String,
/// Path or URL to a JSON schema, which may include reduction annotations.
#[clap(long, conflicts_with_all(&["source", "collection"]), requires("key"))]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious about using conflicts_with_all here. We have 2 pairs of options that are mutually exclusive. The docs don't indicate that these pairs are linked or that you can't mix and match them. Would a subcommand enum be helpful here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, what I'd ideally like is to express these two sets of mutually exclusive arguments as an enum. I tried using somehting like this, but couldn't get it to work with clap:

pub enum SchemaAndKeySource {
  Direct {
    schema: String,
    key: Vec<String>,
  }
  Build {
    source: String,
    collection: String,
  }
}

I have a general sense that subcommands should be used for verbs, rather than for grouping arguments, which was why I went with the mutual exclusion flags. Ideally we'd be able to map those flags to different rust enums without requiring an extra subcommand, which feels like it should be doable.

I found this thread for structopt, which eventually led me to this issue, which seems like it'll eventually get us what we want. They have a proposed workaround there, too, which I can take a look at, though I'd prefer to do that in a follow on PR.

Comment on lines 157 to 162
for coll in output.collections.iter() {
eprintln!("collection: {:?}", coll);
}
for coll in output.built_collections.iter() {
eprintln!("built_collection: {:?}", coll);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We're deliberately outputting this directly to stderr, rather than as a tracing message?

Copy link
Member Author

Choose a reason for hiding this comment

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

lol whoops! That was just a little println debugging that shouldn't have made it in. I'll remove it.

Comment on lines +76 to +82
fn run_internal<T, F>(
subcommand_args: InternalSubcommandArgs<T>,
run_fn: F,
) -> Result<(), anyhow::Error>
where
T: clap::Args + std::fmt::Debug,
F: FnOnce(T) -> Result<(), anyhow::Error>,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is nice. Subcommands can only be passed arguments that are relevant to them. 👍

@@ -0,0 +1,105 @@
use assert_cmd::{assert::Assert, Command};
Copy link
Contributor

Choose a reason for hiding this comment

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

Neat. 📸

Comment on lines +159 to +160
${PKGDIR}/bin/flowctl-rs: ${RUSTBIN}/flowctl-rs
cp ${RUSTBIN}/flowctl-rs $@
Copy link
Contributor

Choose a reason for hiding this comment

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

I just realized that I didn't have .build/bin in my PATH, but rather that I've always been picking up flowctl from my ~/go/bin. 🙃

@psFried psFried merged commit abda1bd into master Feb 9, 2022
@psFried psFried deleted the phil/flowctl-subcomands branch February 9, 2022 15:04
@oliviamiannone oliviamiannone added the docs complete / NA No (more) doc work related to this PR label Feb 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs complete / NA No (more) doc work related to this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants