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

Generate DB CLI commands for Teleterm from tsh daemon #11835

Merged
merged 17 commits into from
Apr 14, 2022

Conversation

ravicious
Copy link
Member

@ravicious ravicious commented Apr 8, 2022

  • Best reviewed commit-by-commit.
  • Files under lib/teleterm/api/protogen are autogenerated from proto files.

To test this change in Teleterm, you need a dev version of Teleterm with gravitational/webapps#726.

Why

When you connect to a cluster with Teleterm and click "Connect" next to a database, it sets up the equivalent of tsh proxy db --tunnel (--tunnel was added in #11720).

However, up until this point, Teleterm was constructing the DB CLI commands by hand, meaning that each time the Database Access team adds support for a new protocol, we'd need to update Teleterm. In general, we'd need to keep both places in sync.

What

@smallinsky suggested to generate those inside the tsh daemon and this is what this PR achieves.

On top of that, it adds GetRelativeConnectCommand so that Teleterm doesn't have to show absolute paths to the binaries.

@ravicious ravicious marked this pull request as ready for review April 8, 2022 16:40
@github-actions github-actions bot requested review from ibeckermayer and zmb3 April 8, 2022 16:40
@github-actions github-actions bot added the tsh tsh - Teleport's command line tool for logging into nodes running Teleport. label Apr 8, 2022
@ravicious ravicious requested review from r0mant and jakule and removed request for zmb3 and ibeckermayer April 8, 2022 16:41
@ravicious
Copy link
Member Author

I'll fix the lint problems on Monday.

Comment on lines 239 to 251
// Check for mysql binary. Return with error as mysql and mariadb are missing. There is nothing else we can do here.
if !c.isMySQLBinAvailable() {
return nil, trace.NotFound("neither %q nor %q CLI clients were found, please make sure an appropriate CLI client is available in $PATH", mysqlBin, mariadbBin)
}

Copy link
Member Author

Choose a reason for hiding this comment

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

This was removed so that dbcmd doesn't fail for Teleterm if the user doesn't have the binaries installed.

For the most part, the DB CLI command in Teleterm has a more "decorative" function – unlike tsh db connect, it doesn't have to actually work on the user's machine.

Copy link
Collaborator

@r0mant r0mant left a comment

Choose a reason for hiding this comment

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

Left a few nits but mostly lgtm.

lib/client/db/dbcmd/dbcmd.go Outdated Show resolved Hide resolved
lib/client/db/dbcmd/dbcmd.go Outdated Show resolved Hide resolved
lib/client/db/dbcmd/dbcmd.go Show resolved Hide resolved
lib/client/db/dbcmd/dbcmd.go Show resolved Hide resolved
lib/teleterm/gateway/gateway.go Outdated Show resolved Hide resolved
lib/teleterm/gateway/gateway.go Show resolved Hide resolved
Copy link
Contributor

@smallinsky smallinsky left a comment

Choose a reason for hiding this comment

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

I took quick look and left some comments.

lib/teleterm/clusters/cluster_gateways.go Outdated Show resolved Hide resolved
Comment on lines +76 to +80
routeToDb := tlsca.RouteToDatabase{
ServiceName: gw.TargetName,
Protocol: gw.Protocol,
Username: gw.TargetUser,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems that database name is missing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, for now there's no way for the user to specify the db name anyway.

}

cmd, err := dbcmd.NewCmdBuilder(c.clusterClient, &c.status, &routeToDb, c.URI.GetRootClusterName(),
dbcmd.WithLocalProxy(gw.LocalAddress, gw.LocalPortInt(), ""),
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if it the last argument - caPath should be empty. For example mongo, and redis commands are using this arg to overwrite CA

if c.options.caPath != "" {

Copy link
Member Author

Choose a reason for hiding this comment

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

They do this only in the absence of the noTLS option and this callsite here will always use dbcmd.WithNoTLS().

Perhaps in the future it'd be worthwhile to refactor connectionCommandOpts so that it's not possible to pass mutually exclusive options.

@ravicious ravicious requested review from r0mant and smallinsky April 11, 2022 14:26
lib/client/db/dbcmd/dbcmd.go Outdated Show resolved Hide resolved
lib/client/db/dbcmd/dbcmd.go Show resolved Hide resolved
lib/client/db/dbcmd/dbcmd.go Outdated Show resolved Hide resolved
}

// Check for mysql binary. Return with error as mysql and mariadb are missing. There is nothing else we can do here.
if !c.isMySQLBinAvailable() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way for Teleterm to deal with that error?

  1. Currently if none of the supported binaries are installed tsh will print mysql not found not mentioning that mariadb` is also a supported client
  2. If Teleterm fails on every error returned from CLIBuildder then another person working on that code can easily return an error and break the Teleterm. If this is the case I'd suggest removing the error from returned values.

Copy link
Member Author

Choose a reason for hiding this comment

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

If Teleterm fails on every error returned from CLIBuildder then another person working on that code can easily return an error and break the Teleterm.

Good point.

The fundamental issue is that tsh db connect expects dbcmd to return a command that will work and if it can't provide one, it should either return an appropriate error or attempt to execute the command which will result in the <binary> not found error.

tsh db connect also executes dbcmd only when the command is actually needed. So if someone has a cluster with a Postgres db but they don't have psql installed it and they never try to access it, nothing bad ever happens.

Teleterm on the other hand doesn't expect this command to work. It's more of a "if you have the CLI client installed on your system, this command should connect you to that db". It also needs this command any time it creates a local proxy for the db, but the user might not even want to use that command. They might want to use a GUI app. So again, in this case we don't really care if the binary is actually on the system.


@jakule What if we added a tolerateMissingCLIClient flag to connectionCommandOpts? If it's present, dbcmd would not return an error here, but rather c.getMySQLOracleCommand().

#11843 added the printFormat flag so that tsh db config can wrap Postgres connection strings in quotes. With tolerateMissingCLIClient, the option usage would look like this:

use case printFormat tolerateMissingCLIClient
tsh db config
tsh db connect
Teleterm

Copy link
Member Author

Choose a reason for hiding this comment

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

@jakule I added a comment which adds said option, please let me know what you think.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fine by me. I'd just change the name of that flag to ignoreMissingBin or skipBinCheck maybe?

Copy link
Contributor

Choose a reason for hiding this comment

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

Please also add a test with this flag set.

Copy link
Member Author

Choose a reason for hiding this comment

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

Heh, I thought about a name like this. However, for all the other protocols, dbcmd doesn't actually check if the binary is there or not – attempting to run the resulting command is just going to fail with a regular shell error about a missing binary.

At the moment it really is just a special case for MySQL where instead of telling the user that mysql doesn't exist we also want to point out that mariadb is a valid option too. So I didn't want to use a field name that would suggest that if the field is not present then the check will be done.

In that sense it's more of a caller telling dbcmd "I'm okay with the CLI missing on user's system".

Copy link
Member Author

Choose a reason for hiding this comment

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

Please also add a test with this flag set.

Yep, I already added one that makes mysql and mariadb not available and expects that the method will not return an error.

@ravicious ravicious force-pushed the ravicious/teleterm-db-cli-command branch from 1e650a8 to dd1d11c Compare April 12, 2022 14:49
@ravicious ravicious requested a review from jakule April 12, 2022 14:52
@ravicious ravicious force-pushed the ravicious/teleterm-db-cli-command branch from b73446b to d60bf57 Compare April 12, 2022 14:56
@ravicious ravicious enabled auto-merge (squash) April 13, 2022 11:11
@ravicious ravicious disabled auto-merge April 13, 2022 14:41
@ravicious ravicious enabled auto-merge (squash) April 13, 2022 15:26
@ravicious ravicious disabled auto-merge April 13, 2022 16:02
@ravicious ravicious enabled auto-merge (squash) April 14, 2022 08:08
@ravicious ravicious merged commit 60f5972 into master Apr 14, 2022
@ravicious ravicious deleted the ravicious/teleterm-db-cli-command branch April 14, 2022 08:29
ravicious added a commit that referenced this pull request Apr 25, 2022
* Extract dbcmd.go into a new package under lib/client/db/dbcmd

* Use dbcmd to generate CliCommand for gateways

* Return relative db command from tsh daemon

* Add WithTolarateMissingCLIClient func to dbcmd
ravicious added a commit that referenced this pull request Apr 27, 2022
* Extract dbcmd.go into a new package under lib/client/db/dbcmd

* Use dbcmd to generate CliCommand for gateways

* Return relative db command from tsh daemon

* Add WithTolarateMissingCLIClient func to dbcmd
ravicious added a commit that referenced this pull request Apr 27, 2022
…commands for Teleport Connect (#12206)

* Quote postgres connection string for printing to terminals (#11843)

* Generate DB CLI commands for Teleterm from tsh daemon (#11835)

* Extract dbcmd.go into a new package under lib/client/db/dbcmd

* Use dbcmd to generate CliCommand for gateways

* Return relative db command from tsh daemon

* Add WithTolarateMissingCLIClient func to dbcmd

Co-authored-by: STeve (Xin) Huang <xin.huang@goteleport.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tsh tsh - Teleport's command line tool for logging into nodes running Teleport.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants