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

CLI Unification: Root Command #917

Merged
merged 28 commits into from
Jul 20, 2021
Merged

CLI Unification: Root Command #917

merged 28 commits into from
Jul 20, 2021

Conversation

brianstrauch
Copy link
Member

@brianstrauch brianstrauch commented Jul 7, 2021

Checklist

  1. [CRUCIAL] Is the change for CP or CCloud functionalities that are already live in prod?

    • yes: ok
  2. Did you add/update any commands that accept secrets as args/flags?

    • no: ok

What

  • The root command no longer requires cliName, which was previously passed in as a linker flag (-ldflags "-X main.cliName=confluent")
  • The CLI will not run if there are any errors while loading the config file
  • When user isn't logged in, only commands which can exist for cloud and on-prem can be run
  • After login, based on IsCloud() and IsOnPrem(), show the commands available in the user's current context.

At this point, the confluent binary is unified! Future PRs will unify individual commands.

Plan of action: https://confluentinc.atlassian.net/wiki/spaces/Foundations/pages/2423849814/1-Pager+CLI+Unification+Implementation+Details

Test & Review

New unit and integration tests based on showing appropriate commands

Open questions / Follow ups

Should the confluent local command be always shown, since it doesn't require login? Are there any other commands that don't require a login that I'm missing?

brianstrauch and others added 15 commits July 1, 2021 19:04
* unify config command

* unified config file, IsCloud and IsOnPrem

* consolidate ccloud hostnames var

* finish config unification and test

* add golden files

* check for test url second

* add back missing return

* support all cpdev platforms

* trim trailing slash from platform names, and use contains

* revert trim trailing slash

* fix error
@brianstrauch brianstrauch requested a review from a team as a code owner July 7, 2021 23:32
Copy link
Contributor

@mtodzo mtodzo left a comment

Choose a reason for hiding this comment

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

looks awesome !

cmd/confluent/main.go Show resolved Hide resolved
internal/cmd/command.go Outdated Show resolved Hide resolved
Comment on lines +88 to +91
// TODO: Remove once unification is complete
cliName := "confluent"
if cfg.IsCloud() {
cliName = "ccloud"
Copy link
Contributor

Choose a reason for hiding this comment

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

is this meant to be deleted?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the config file is loaded in the main function now. The CLI needs a correctly formatted config file in order to work, since it shows a certain subset of commands based on the contents of the config file.

isTest = "false"
)

func main() {
viper.AutomaticEnv()
cfg, err := cmd.LoadConfig()
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to fail immediately because you need the config to tell if it's ccloud or confluent?

Copy link
Contributor

Choose a reason for hiding this comment

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

i forget if that was a field added to the config .. or if you're just parsing the url from the context name but either way

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep exactly. We're using the --url flag to determine whether we should log in to cloud or on-prem, and then once we log in and the context gets stored, we use the current context's platform name (a config field) to decide between cloud and on-prem

internal/cmd/login/command.go Show resolved Hide resolved
@@ -44,7 +45,6 @@ const DoNotTrack = "do-not-track-analytics"
// PreRun is the standard PreRunner implementation
type PreRun struct {
Config *v3.Config
ConfigLoadingError error
Copy link
Contributor

Choose a reason for hiding this comment

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

the part of me that doesn't love how coupled the CLI is with the config wants to keep this (i.e. not fail immediately on config load err) ... i.e. confluent kafka topic list could work if you have the login env vars set and passed a --cluster and --environment value

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh interesting... didn't know that was a thing you could do. I'll have to think about this some more but I wonder if that's something we want people to be able to do in the first place; like, why can kafka commands bypass the login command, but not other commands.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I've thought about this a bit and I want to make a proper config a hard requirement. If a user changed their config file somehow and it broke, they would see a limited subset of the commands and get no help with how to fix it.

For example, if a user had the intention of using the CLI for listing their Kafka clusters, and the kafka command wasn't showing up (even though they thought they had a working config file) they'd be very confused.

Copy link
Contributor

Choose a reason for hiding this comment

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

i think this makes sense .. and i don't think we've seen any customer feedback around not wanting a config file but cc: @DABH since we've discussed not requiring a config file

Copy link
Contributor

Choose a reason for hiding this comment

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

@DABH the tldr is that the config is now a hard requirement (fail immediately if it doesn't load) since the config is needed to determine whether the user is logged into ccloud or on-prem

Copy link
Member Author

@brianstrauch brianstrauch Jul 13, 2021

Choose a reason for hiding this comment

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

Just want to clarify that if there's no config, then it shows the default set of commands that don't require authentication (login, logout, completion, config, help, local, update, version).

It only fails if the config exists and is broken in some way.

The only thing this doesn't support (and maybe should?) is running the commands mentioned above with a broken config. Although... a bunch of the commands listed above read from or write to the config (config, login, logout, update), so they would fail anyway.

At the end of the day, it looks like the only (useful) functionality changing this would enable is being able to run completion, help, local, and version with a broken config.

Copy link
Contributor

Choose a reason for hiding this comment

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

I actually think we would like to be able to run without a config file. The use case is multiple instances of the CLI being used on the same machine/user at the same time, e.g. on a CI machine where multiple jobs run simultaneously. In fact, we've advertised this capability as "stateless mode" -- you can just pass flags for whatever credentials/cluster/env you need etc., and assuming there are valid credentials (env vars / netrc / etc.), the command will work, regardless of what's in the config file, if the config file is corrupted, etc.

I don't think we really want to totally break this functionality. But I do see the problem with needing to know what version of a command to run. So maybe we change things a bit... e.g. we could require an extra flag like "--context"? But that would indeed require at least having a config file. Can we think about this a bit more?

internal/pkg/config/v3/config.go Show resolved Hide resolved
internal/pkg/utils/utils.go Show resolved Hide resolved
test/fixtures/output/help/help-no-context.golden Outdated Show resolved Hide resolved
@mtodzo mtodzo self-requested a review July 15, 2021 16:40
cmd/lint/main.go Outdated
CurrentContext: "no context",
},
{
Contexts: map[string]*v3.Context{"cloud": {PlatformName: testserver.TestCloudURL.String()}},
Copy link
Contributor

Choose a reason for hiding this comment

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

When does this run, during make lint-go? if so im not sure the test servers will have been started so testserver.TestCloudURL might be empty

Copy link
Member Author

Choose a reason for hiding this comment

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

make lint-go runs golangci-lint. This is the main file for make lint-cli, which lints command descriptions/flags. There are three possible subsets of commands that need to be linted, so we need to pass in three configs.

testserver.TestCloudURL.String() is a constant, so this works fine! But... now that you mention it, it would be cleaner to pass in confluent.cloud to the second config, because they're not technically tests.

@DABH
Copy link
Contributor

DABH commented Jul 15, 2021

Should the confluent local command be always shown, since it doesn't require login? Are there any other commands that don't require a login that I'm missing?

Yeah, I think this is ok... you do need to have CP downloaded in order to use these commands (confluent local doesn't download CP for you), but, someone who doesn't have a CP installation with MDS setup (i.e. can't login to CP) might still want to run local commands.

@DABH
Copy link
Contributor

DABH commented Jul 16, 2021

@brianstrauch Jenkins doesn't like this:
Error: unknown command "secret" for "confluent"\nRun \'confluent --help\' for usage.\
So there might be a bit of extra work to do here :|

@brianstrauch brianstrauch merged commit 90440c2 into main Jul 20, 2021
@brianstrauch brianstrauch deleted the unify-confluent branch July 20, 2021 22:19
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.

None yet

3 participants