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

Make several CLI commands testable #86

Merged
merged 7 commits into from
Dec 27, 2017

Conversation

pcalcado
Copy link
Contributor

As I work on the diagnosis CLI experience, I had to go through our current CLI commands and understand them better. I've written tests and refactored things a bit to document this understanding.

@pcalcado pcalcado self-assigned this Dec 22, 2017
@pcalcado pcalcado force-pushed the phil/49-conduit-when-pod-doesnt-exist branch from db7cb4e to c49c7e7 Compare December 22, 2017 02:39
Copy link
Member

@siggy siggy left a comment

Choose a reason for hiding this comment

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

awesome! a couple minor comments...

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the client and server version information",
Long: "Print the client and server version information.",
Args: cobra.NoArgs,
Run: exitSilentlyOnError(func(cmd *cobra.Command, args []string) error {
fmt.Println("Client version: " + controller.Version)
Copy link
Member

Choose a reason for hiding this comment

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

Previously if something went wrong with k8s/server, we'd get output like this:

$ conduit version
Client version: v0.0.1
Server version: unavailable
$ echo $?
2

... with this change conduit version now prints nothing:

$ conduit version
$ echo $?
2

I'd rather know the client version, and get some feedback that something's not working. This is similar to how kubectl works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@siggy
It still prints the version:

$ conduit version
Client version: v0.1.0
Server version: v0.1.0
$ bin/go-run cli version
Client version: v0.1.1
Server version: v0.1.0
$ minikube stop > /dev/null
$ bin/go-run cli version
github.com/runconduit/conduit/cli
Client version: v0.1.1
Server version: unavailable

The difference, I believe, is that err here means "could not instantiate kubectl", not "could not get version from server". The logic that handles errors from the API was moved here: https://github.com/runconduit/conduit/pull/86/files/c49c7e738bef442dbaba164f812c85a25b8d3144#diff-b784f3ae92cb061761114526d43f2e33R58 and is tested here: https://github.com/runconduit/conduit/pull/86/files/c49c7e738bef442dbaba164f812c85a25b8d3144#diff-edf10645fffdcf276967004f4a31ac4fR29

return nil, err
}

func newApiClient(kubeApi k8s.KubernetesApi) (pb.ApiClient, error) {
Copy link
Member

Choose a reason for hiding this comment

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

curious: was this change to newApiClient needed for this round of test changes, or is it in anticipation of future testing? how does this change relate to mockApiClient?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to be consistent with the way we create other objects. With this PR we have every command instantiating the objects it needs and wiring them together. Arguably this function should not be in the root command but rather follow the pattern established elsewhere and be something like conduitclient.MakeApiClient(kubeApi k8s.KubernetesApi) (pb.ApiClient, error), but I didn't want to propose something like this before there was an actual need for it.

var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the client and server version information",
Long: "Print the client and server version information.",
Args: cobra.NoArgs,
Run: exitSilentlyOnError(func(cmd *cobra.Command, args []string) error {
fmt.Println("Client version: " + controller.Version)
Copy link
Member

Choose a reason for hiding this comment

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

I'm running this from a Docker container, perhaps that's why I see no output?

If either k8s.MakeK8sAPi() or newApiClient() fail, it prints nothing. I think we should print the client version no matter what, and then perhaps let the user know what went wrong.

@pcalcado pcalcado force-pushed the phil/49-conduit-when-pod-doesnt-exist branch 9 times, most recently from e3b0859 to 64e30a5 Compare December 27, 2017 17:01
@pcalcado
Copy link
Contributor Author

@siggy I can't reproduce the UX issue your reported on #86 (review) , but I have the impression that this commit solved the problem: 64e30a5 could you test?

Also, I have no idea why this says the DCO isn't there?

Phil Calcado added 7 commits December 27, 2017 12:39
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
Signed-off-by: Phil Calcado <phil@buoyant.io>
@pcalcado pcalcado force-pushed the phil/49-conduit-when-pod-doesnt-exist branch from 64e30a5 to 2e2598b Compare December 27, 2017 17:39
Copy link
Member

@siggy siggy left a comment

Choose a reason for hiding this comment

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

you are correct this was never reproducible with your branch. i had forgotten to set DOCKER_FORCE_BUILD and had a 3-week old conduit binary in my docker image. apologies for the delay here.

i've left one comment re: double printing of error messages. not a big deal. it would also be fine to roll back to your original implementation since that worked anyway.

cli/cmd/root.go Outdated
return func(cmd *cobra.Command, args []string) {
if err := f(cmd, args); err != nil {
os.Exit(2) // Reserve 1 for usage errors.
fmt.Fprintln(os.Stderr, err)
Copy link
Member

Choose a reason for hiding this comment

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

this causes errors to be printed twice:

$ conduit version --kubeconfig foo
error instantiating Kubernetes API client: stat foo: no such file or directory
Client version: v0.1.1
Server version: unavailable
error instantiating Kubernetes API client: stat foo: no such file or directory

}
})

t.Run("Returns empty list if no [ods found", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

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

[ods

@pcalcado
Copy link
Contributor Author

@siggy awesome, thanks! I will remove the last commit and later start a conversation around how we do output in the CLI so that we have a standard way to print

@pcalcado pcalcado force-pushed the phil/49-conduit-when-pod-doesnt-exist branch from 2e2598b to da97dc6 Compare December 27, 2017 18:59
@pcalcado pcalcado merged commit 31e9846 into master Dec 27, 2017
@pcalcado pcalcado deleted the phil/49-conduit-when-pod-doesnt-exist branch December 27, 2017 19:12
khappucino pushed a commit to Nordstrom/linkerd2 that referenced this pull request Mar 5, 2019
The `control::destination` exposes an important trait, `Bind`, that
abstracts the logic of instantiating a new service for an individual
endpoint (i.e., in a load balancer).

This interface is not specific to our service discovery implementation,
and can easily be used to model other types of client factory.

In the spirit of consolidating our HTTP-specific logic, and making the
core APIs of the proxy more visible, this change renames the `Bind`
trait to `NewClient`, simplifies the trait to have fewer type
parameters, and documents this new generalized API.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants