-
Notifications
You must be signed in to change notification settings - Fork 4.7k
make new-app error reports clearer #12978
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
Conversation
pkg/generate/app/cmd/newapp.go
Outdated
remote, err := app.IsRemoteRepository(s) | ||
c.ArgumentClassificationErrors["Remote access"] = err | ||
local, err := app.IsDirectory(s) | ||
c.ArgumentClassificationErrors["Local access"] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this whole block be protected by the if !validated condition, to mimic the switch behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also only set the classification errors is err!=nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was originally that way (whole block, etc .etc.), and then broke slightly from that norm in this sense:
- The information as to whether the arg satisfied any of the tests seemed useful to me
- note I don't update the
c.Components
etc. for any of the subsequent classifications on a match has been made ... in that sense I preserve the switch behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And on classificatnoi errors and err != nil, again, that was intentional. If a classification passed, I wanted it illustrated by the fact that the error field was nil. If I don't add a key / nil err pair, then unless you know the entire list of classifications, you don't know what has passed if we only list the actual errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how the additional information is useful since there's nothing the user can do about it (eg if we think it's an environment variable, it doesn't really matter if we also think it's a source repo, or are sure it's not a source repo because of error X, it's still going to get processed/consumed as an environment variable).
If anything it may just lead to more confusion since anytime new-app fails overall(for unrelated reasons), it's going to print out messages talking about the error it got when trying to treat an env variable argument as a source repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And on classificatnoi errors and err != nil, again, that was intentional. If a classification passed, I wanted it illustrated by the fact that the error field was nil. If I don't add a key / nil err pair, then unless you know the entire list of classifications, you don't know what has passed if we only list the actual errors.
yeah i sort of figured that was the intention, but for an end user it's a pretty ugly/confusing output. I might be convinced of keeping the nil value and doing better processing when printing the errors out to reformat the "nil" to something more informative to the user, but overall I think doing anything with it is tipping too far on the side of "what gabe+ben want to see to debug the problem" and not "what is useful to a user to see to know what they should do to fix it". For example "Component reference" means nothing at all to an end user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some internal ping-pong, I landed on not feeling strongly enough to dig in one side or the other :-) I'll switch back to the closer mimic of the switch behavior.
pkg/generate/app/cmd/newapp.go
Outdated
validated = true | ||
} | ||
|
||
err = app.IsComponentReference(s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, guard with if !validated
pkg/generate/app/cmd/newapp.go
Outdated
} | ||
|
||
err = app.IsComponentReference(s) | ||
c.ArgumentClassificationErrors["Component reference processing"] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only set this if err!=nil?
pkg/generate/app/cmd/newapp.go
Outdated
} | ||
|
||
rc, err = app.IsPossibleTemplateFile(s) | ||
c.ArgumentClassificationErrors["Template processing"] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comments as above.
pkg/cmd/cli/cmd/newapp.go
Outdated
@@ -612,7 +612,13 @@ func handleRunError(err error, baseName, commandName, commandPath string) error | |||
transformError(err, baseName, commandName, commandPath, groups) | |||
} | |||
buf := &bytes.Buffer{} | |||
fmt.Fprintf(buf, "Prior to API Object processing, here were the results from application argument classification:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only print this if len(config.ArgumentClassificationErrors)>0
(in conjunction w/ not adding things to that map unless the value is non-nil, as mentioned below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK ... still debating the suggestions above, I agree with the len check.
pkg/cmd/cli/cmd/newapp.go
Outdated
for key, value := range config.ArgumentClassificationErrors { | ||
fmt.Fprintf(buf, fmt.Sprintf("\n%s: %v\n", key, value)) | ||
} | ||
fmt.Fprint(buf, "\n\nThen, the following errors were noted during API Object processing:\n\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/noted/occurred/ but this test will also have to be reworked to account for the possibility that it is the first output, once you make the change i suggested above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do rewording ... agreement on above suggestions still pending
What the heck is "API Object processing" and why is it showing up in an error message to an end user? |
:-) It was my attempt to categorize/summarize the fact that Prior to the REST interactions with the master that result in creation, there is client side interpretation of the arguments that result in git invocations, file system checks, that could or could not fail for various reasons. I tasked with exposing those failures for debug when That opening phrase was an attempt to provided context. But of course suggestions to change are appreciated (assuming you agree with exposing those errors if the command fails). |
Perhaps replace the entire fist sentence with: "Attempts to classify the arguments resulted in these errors:" The for the next sentence go with "The following errors occurred after argument classification:" |
a4ae8a9
to
ff09cdc
Compare
Updates to @bparees comments pushed. Fixing "API Object processing" still pending ... waiting a bit to see what feedback arrives. |
pkg/cmd/cli/cmd/newapp.go
Outdated
@@ -612,7 +612,15 @@ func handleRunError(err error, baseName, commandName, commandPath string) error | |||
transformError(err, baseName, commandName, commandPath, groups) | |||
} | |||
buf := &bytes.Buffer{} | |||
if config.ArgumentClassificationErrors != nil && len(config.ArgumentClassificationErrors) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config.ArgumentClassificationErrors != nil
is unnecessary: len(nil) == 0 in golang.
pkg/cmd/cli/cmd/newbuild.go
Outdated
@@ -271,7 +271,15 @@ func handleBuildError(err error, baseName, commandName, commandPath string) erro | |||
transformBuildError(err, baseName, commandName, commandPath, groups) | |||
} | |||
buf := &bytes.Buffer{} | |||
if config.ArgumentClassificationErrors != nil && len(config.ArgumentClassificationErrors) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config.ArgumentClassificationErrors != nil
is unnecessary: len(nil) == 0 in golang.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/generate/app/cmd/newapp.go
Outdated
continue | ||
} | ||
|
||
// had to move off of elegant switch to capture errors for future display, but mimic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems more like a commit comment than a code comment ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It certainly is .... between your comment and the exchange I had with @bparees, I believe the explanation has been sufficiently proliferated :-)
deleted with next push
pkg/generate/app/cmd/newapp.go
Outdated
for _, s := range args { | ||
switch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're ditching the switch statement, can you refactor into a separate function which then allows you to avoid all the nested ifs? i.e.:
if foo {
// something
return
}
if bar {
// something else
return
}
rather than
if foo {
// something
} else {
if bar {
// something else
} else {
if baz ...
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, the refactor into functions made me realize I could preserve the switch - thanks!... part of next push
Comments added. For what my view is worth, I feel pretty reluctant about this change on the basis that it feels like it's building more stuff on top of our shaky foundations and locking us more into them. I'm concerned this will make future code maintenance/cleanup harder, rather than easier. If possible, I'd sooner see one of the following:
|
ff09cdc
to
023acd6
Compare
Updates pushed include:
On @jim-minter 's concerns outside of the code change comments:
My two cents. @bparees - based on the responses from various folks, where's your head wrt this? |
I still want to see this done, the current experience is bad.
i'm not sure what is particularly heavyweight about this, curious if the changes resulting from your feedback make you feel any better about it.
definitely not a fan of this, the current error behavior is pretty baffling to users. (and this PR spawned from a user issue in which the user was so confused by the behavior that they thought new-app didn't support ip address based source repos)
i'm not against also doing this, at this point i'm sure a lot of us have a mental wishlist of "if i was writing new-app from scratch...." and it would certainly not hurt to have that written down.
that's what --code, --template, --image, etc are for. and it is true that in the case of the original issue the user hit, if they'd rerun the command w/ --code they'd have gotten a more useful error:
but obviously this user did not understand the failure they'd hit sufficiently to realize new-app had mis-categorized the argument and that telling new-app what the arg type was might get them more information...so i'm not convinced that's a sufficient solution (as evidenced by it not having been sufficient for the user who hit this) |
pkg/cmd/cli/cmd/newapp.go
Outdated
@@ -612,7 +612,15 @@ func handleRunError(err error, baseName, commandName, commandPath string) error | |||
transformError(err, baseName, commandName, commandPath, groups) | |||
} | |||
buf := &bytes.Buffer{} | |||
if len(config.ArgumentClassificationErrors) > 0 { | |||
fmt.Fprintf(buf, "Attempts to classify the arguments resulted in these errors:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Errors occurred while determining argument types:"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/cmd/cli/cmd/newapp.go
Outdated
for key, value := range config.ArgumentClassificationErrors { | ||
fmt.Fprintf(buf, fmt.Sprintf("\n%s: %v\n", key, value)) | ||
} | ||
fmt.Fprint(buf, "\nThe following errors occurred during application creation:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Errors occurred during resource creation:"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/cmd/cli/cmd/newapp.go
Outdated
@@ -599,7 +599,7 @@ func retryBuildConfig(info *resource.Info, err error) runtime.Object { | |||
return nil | |||
} | |||
|
|||
func handleRunError(err error, baseName, commandName, commandPath string) error { | |||
func handleRunError(err error, baseName, commandName, commandPath string, config *newcmd.AppConfig) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only difference between this and handleBuildError is which function is invoked for transformation...seems like an opportunity to collapse some code (pass the transform function in as an argument)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(and might make @jim-minter feel better about the weight of the changes :) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/cmd/cli/cmd/newbuild.go
Outdated
for _, group := range groups { | ||
//TODO how coupled are we to kcmdutil.MultipleErrors ... format is compressed, non-optimal readability |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not seeing a current need to change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
10-4
pkg/generate/app/cmd/newapp.go
Outdated
c.Components = append(c.Components, s) | ||
return true | ||
} | ||
c.ArgumentClassificationErrors["Component reference processing"] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd like to see another term used here that will have meaning to the user. I think this is essentially checking if the value is either:
- an image
- an imagestreamtag
- a template that exists in the cluster(?)
if it weren't for 3 this would be easier to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll work off of the terminology in the suggestion
pkg/generate/app/cmd/newapp.go
Outdated
} | ||
|
||
if derr != nil { | ||
c.ArgumentClassificationErrors["Local access"] = derr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these two error keys don't make it clear the failure was related to trying to treat the argument as a source repo. (remote access to what? local access to what?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll work off of the terminology in the suggestion
pkg/generate/app/cmd/newapp.go
Outdated
case c.addEnvironmentArguments(s): | ||
case c.addSourceArguments(s): | ||
case c.addComponentArguments(s): | ||
case c.addTemplateArguments(s): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the user passes multiple arguments, this error accumulation and reporting logic breaks down. You need to accumulate the ArgumentClassificationErrors on a per argument basis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep I'll include the arg string in the key - good catch
test/cmd/newapp.sh
Outdated
os::cmd::expect_failure_and_text 'oc new-app https://githb.com/openshift/nodejs-e' 'Remote access: ' | ||
os::cmd::expect_failure_and_text 'oc new-build --strategy=docker https://192.30.253.113/openshift/ruby-hello-world.git' 'Remote access: ' | ||
os::cmd::expect_failure_and_text 'oc new-build https://www.google.com/openshift/nodejs-e' 'Remote access: ' | ||
os::cmd::expect_failure_and_text 'oc new-build https://githb.com/openshift/nodejs-e' 'Remote access: ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a test w/ multiple arguments that all fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
023acd6
to
75cabce
Compare
responses to latest @bparees comments pushed |
pkg/cmd/cli/cmd/newapp.go
Outdated
@@ -599,7 +599,7 @@ func retryBuildConfig(info *resource.Info, err error) runtime.Object { | |||
return nil | |||
} | |||
|
|||
func handleRunError(err error, baseName, commandName, commandPath string) error { | |||
func handleError(err error, baseName, commandName, commandPath string, config *newcmd.AppConfig, f func(err error, baseName, commandName, commandPath string, groups errorGroups)) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename f to transformError?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure more informative less terse ... part of next push
pkg/cmd/cli/cmd/newapp.go
Outdated
for key, value := range config.ArgumentClassificationErrors { | ||
fmt.Fprintf(buf, fmt.Sprintf("\n%s: %v\n", key, value)) | ||
} | ||
fmt.Fprint(buf, "\nErrors occurred during resource creation:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be split so printing the \n is inside the if clause and printing the rest of the text outside?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I debated putting the "Errors occurred during resource creation:" in even if there were no ArgumentClassificationErrors, simply to add some context and clarification around the terse kcmdutil.MultipleErrors output.
You've tipped me in that direction. Part of next push.
pkg/generate/app/cmd/newapp.go
Outdated
c.Components = append(c.Components, s) | ||
return true | ||
} | ||
c.ArgumentClassificationErrors[fmt.Sprintf("%s as a imagestream tag or docker image reference ", s)] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a->an in a imagestream tag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/generate/app/cmd/newapp.go
Outdated
@@ -117,6 +117,8 @@ type AppConfig struct { | |||
|
|||
OSClient client.Interface | |||
OriginNamespace string | |||
|
|||
ArgumentClassificationErrors map[string]error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether
ArgumentClassificationErrors []struct {
Key string
Value error
}
may prove better, to keep ordering of messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm ... yeah, slightly more cumbersome to use, but the implementation does prescribe a precedence.
I'll prototype and see if it looks palatable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and then I'll be quiet :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-)
change is palatable ... about to push
pkg/generate/app/cmd/newapp.go
Outdated
return true | ||
} | ||
if err != nil { | ||
c.ArgumentClassificationErrors[fmt.Sprintf("%s as a template in an accessible project", s)] = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the text right given it says as possible template file
above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
pkg/generate/app/cmd/newapp.go
Outdated
case app.IsPossibleTemplateFile(s): | ||
glog.V(2).Infof("treating %s as possible template file\n", s) | ||
c.Components = append(c.Components, s) | ||
case c.addEnvironmentArguments(s): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wonder whether calling these functions tryToAddFoo might make this a little clearer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
part of next push
@bparees pushed changes stemming from your last set of code comments and updated the sample outputs in the description |
pkg/cmd/cli/cmd/newapp.go
Outdated
} | ||
fmt.Fprint(buf, "\n") | ||
} | ||
fmt.Fprint(buf, "Errors occurred during resource creation:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should also be conditional on there actually being at least one resource creation error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fact that we are in handleErrors
at this point already ensures that there is at least one error. See the if err == nil return snippet at the top. I believe an additional check is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, i see now. thanks.
test/cmd/newapp.sh
Outdated
os::cmd::expect_failure_and_text 'oc new-app https://githb.com/openshift/nodejs-e' 'as a GIT repository URL: ' | ||
os::cmd::expect_failure_and_text 'oc new-build --strategy=docker https://192.30.253.113/openshift/ruby-hello-world.git' 'as a GIT repository URL: ' | ||
os::cmd::expect_failure_and_text 'oc new-build https://www.google.com/openshift/nodejs-e' 'as a GIT repository URL: ' | ||
os::cmd::expect_failure_and_text 'oc new-build https://githb.com/openshift/nodejs-e' 'as a GIT repository URL: ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these all need to be fixed to Git
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doh!! .. the one time I didn't run test-cmd :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
script update pushed
7d0cce7
to
ab9137a
Compare
lgtm but we're going to need a final signoff from @smarterclayton on the error messaging. |
@smarterclayton bump on you take on updated error message examples in PR description - thanks |
ab9137a
to
c0eaf6f
Compare
987dd12
to
0a11b3a
Compare
@smarterclayton bump for review of new error output. |
@openshift/cli-review ptal. |
pkg/cmd/cli/cmd/newapp.go
Outdated
} | ||
fmt.Fprint(buf, "\n") | ||
} | ||
fmt.Fprint(buf, "Errors occurred during resource creation:\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: fmt.Fprintln
could be used instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switch to fmt.Fprintln
pushed
@fabianofranz this lgtm from a cli perspective |
thanks @juanvallejo |
[Test]ing while waiting on the merge queue |
Looks like a new-app extended test is not happy:
Didn't realize this extended test existed. I believe it is getting confused by the new, additional error messages that were added. I'll start working on an update to the extended test to account for the new messages. |
Looks like something happened with pkg/generate/app/cmd/newapp_test.go after one of the rebases. Will need to address that too. |
OK fixes to those two items pushed. [test] |
Evaluated for origin test up to 5fa0f68 |
[merge] |
continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/870/) (Base Commit: 5e64198) |
Evaluated for origin merge up to 5fa0f68 |
continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/870/) (Base Commit: da719a3) (Image: devenv-rhel7_6047) |
Fixes #12892
@openshift/devex ptal
Some sample output: