Route creation with oc new-app#16396
Conversation
|
/unassign @smarterclayton |
jim-minter
left a comment
There was a problem hiding this comment.
Great start @mangirdaz!
pkg/template/controller/readiness.go
Outdated
| return ready, failed, nil | ||
| } | ||
|
|
||
| // checkRouteReadiness checks if host fiels was prepoplated already. |
There was a problem hiding this comment.
s/fiels/field/
s/prepoplated/prepopulated/
| } | ||
|
|
||
| // checkRouteReadiness checks if host fiels was prepoplated already. | ||
| func checkRouteReadiness(oc client.Interface, obj runtime.Object) (bool, bool, error) { |
There was a problem hiding this comment.
Add two tests to TestCheckReadiness in pkg/template/controller/readiness_test.go, showing a Route that will return !ready, and one that will return ready
| deployapi.Kind("DeploymentConfig"): checkDeploymentConfigReadiness, | ||
| batch.Kind("Job"): checkJobReadiness, | ||
| apps.Kind("StatefulSet"): checkStatefulSetReadiness, | ||
| routeapi.Kind("Route"): checkRouteReadiness, |
There was a problem hiding this comment.
You need an additional line routeapi.LegacyKind("Route"): checkRouteReadiness, here. This will handle objects with apiVersion: v1, kind: Route. Your existing line only handles objects with apiVersion: route.openshift.io/v1, kind: Route.
pkg/oc/cli/cmd/newapp.go
Outdated
| } | ||
| case *routeapi.Route: | ||
| if len(t.Spec.Host) > 0 { | ||
| fmt.Fprintf(out, "%sThe Access application via route '%s' \n", indent, t.Spec.Host) |
There was a problem hiding this comment.
s/The Access application/Access your app/
pkg/oc/cli/cmd/newapp.go
Outdated
|
|
||
| type LogsForObjectFunc func(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) | ||
|
|
||
| func containsRoute(item []runtime.Object) bool { |
There was a problem hiding this comment.
I think I'd remove this function and just set a flag variable if you find a Route when iterating result.List.Items in RunNewApp()
pkg/oc/cli/cmd/newapp.go
Outdated
| return false | ||
| } | ||
|
|
||
| func getAllServices(item []runtime.Object) []string { |
There was a problem hiding this comment.
func getServices(items []runtime.Object) []*kapi.Service would be a better signature
pkg/oc/cli/cmd/newapp.go
Outdated
| case len(result.List.Items) > 0: | ||
| //if we dont find a route we give a message to expose it | ||
| if !containsRoute(result.List.Items) { | ||
| //we if dont have any route but have services - suggest commndas to expose those |
pkg/oc/cli/cmd/newapp.go
Outdated
| //we if dont have any route but have services - suggest commndas to expose those | ||
| svc := getAllServices(result.List.Items) | ||
| if len(svc) > 0 { | ||
| fmt.Fprintf(out, "%sApplication is not exposed. You can expose it to outside world by executing one or all of the commands below \n", indent) |
There was a problem hiding this comment.
Not sure on the final wording for this: maybe the following is better?
"%sApp is not exposed. You can expose services to the outside world by executing one or more of the commands below:\n"
|
@mangirdaz also, can you see if you can get a couple of new tests together in test/cmd/newapp.sh ? For example something like |
|
@jim-minter fixed as per comments.
|
|
/test cmd |
pkg/oc/cli/cmd/newapp.go
Outdated
| for _, i := range result.List.Items { | ||
| switch i.(type) { | ||
| case *routeapi.Route: | ||
| containRoute = true |
There was a problem hiding this comment.
I meant to push this up to around line 377 to save the additional iteration - is that possible?
| func getServices(items []runtime.Object) []*kapi.Service { | ||
| var svc []*kapi.Service | ||
| for _, i := range items { | ||
| switch i.(type) { |
There was a problem hiding this comment.
no need to change it, but for reference, you can also do if s, ok := i.(*kapi.Service); ok { svc = append(svc, s) }
| # test deployments are created with the boolean flag and printed in the UI | ||
| os::cmd::expect_success_and_text 'oc new-app mysql --dry-run --as-test' 'This image will be test deployed' | ||
| os::cmd::expect_success_and_text 'oc new-app mysql -o yaml --as-test' 'test: true' | ||
| os::cmd::expect_success_and_text 'oc new-app mysql --as-test' 'Application is not exposed' |
There was a problem hiding this comment.
I think that if you add --dry-run here, it'll save having to clean anything up in the test
There was a problem hiding this comment.
Dry run does not work as we terminate all new-app stuff before we reach output phase. And it makes sense as we dont have what to "expose"
if !o.Action.Verbose() || o.Action.DryRun {
return nil
}
There was a problem hiding this comment.
Ah - then do you need to add some os::cmd::expect_success 'oc delete all --selector="label=something"' lines?
There was a problem hiding this comment.
Added one more new small template as reusing old ones was causing lot of false/positives.
+Added cleaning... This file is so sensitive... you touch one test and 5 starts failing :D
|
/retest |
|
@bparees I think this is nearly there - want to take a look? |
|
@mangirdaz you can/should squash your commits before this gets merged, use |
pkg/oc/cli/cmd/newapp.go
Outdated
| } | ||
| case *routeapi.Route: | ||
| if len(t.Spec.Host) > 0 { | ||
| fmt.Fprintf(out, "%sAccess your application via route '%s' \n", indent, t.Spec.Host) |
There was a problem hiding this comment.
If we find a route object it's possible Host will be empty because the template.Route didn't specify a value. (which means it'll get filled in by the server when the Route object is created). This is where we should really be polling the created object on the server until it has a valid Host value filled in, and then report that value (similar to how your added readiness check works).
There was a problem hiding this comment.
Does this mean we will create blocking process here? Should we poll the server for let's say 5s and if we cant get it we either error or dont print it at all?
There was a problem hiding this comment.
yes i think a cap on how long to wait is a good idea.
There was a problem hiding this comment.
What about this? Sorry for stupid question. Stil trying to get my head around on different implementations styles around the codebase.
// getRouteHost will poll server for host field to be populated. With timout
func getRouteHost(c *newcmd.AppConfig, r *routeapi.Route) (*routeapi.Route, error) {
var route *routeapi.Route
c1 := make(chan string, 1)
go func() {
time.Sleep(time.Second * RoutePollTimoutSeconds)
c1 <- "Route creation timout"
}()
select {
case res := <-c1:
return nil, err.New(res)
case <-time.After(time.Microsecond * 500):
route, err := c.OSClient.Routes(r.Namespace).Get(r.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if route.Spec.Host != "" {
return route, nil
}
}
return route, nil
}
There was a problem hiding this comment.
check out wait.Poll as it's used elsewhere in the codebase.
ba9de15 to
517266e
Compare
f95ba19 to
3a64066
Compare
pkg/oc/cli/cmd/newapp.go
Outdated
| if len(t.Spec.Host) > 0 { | ||
| containsRoute = true | ||
| var route *routeapi.Route | ||
| //check if route processing was complted and host field is prepopulated by router |
pkg/oc/cli/cmd/newapp.go
Outdated
| if route.Spec.Host != "" { | ||
| return true, nil | ||
| } | ||
| return false, coreerror.New(fmt.Sprintf("Timout while polling route %s", t.Name)) |
There was a problem hiding this comment.
this should be return false, nil
3a64066 to
0fbc994
Compare
|
lgtm. @smarterclayton any final concerns? |
pkg/oc/cli/cmd/newapp.go
Outdated
| const NewAppRecommendedCommandName = "new-app" | ||
|
|
||
| // RoutePollTimoutSeconds sets how long new-app command waits for route host to be prepopulated | ||
| const RoutePollTimoutSeconds = 5 |
There was a problem hiding this comment.
const RoutePollTimeout = 5 * time.Second
pkg/oc/cli/cmd/newapp.go
Outdated
|
|
||
| import ( | ||
| "bytes" | ||
| coreerror "errors" |
There was a problem hiding this comment.
fyi: very rare in our codebase to rename core go imports, best avoided. We'll get rid of this import below
pkg/oc/cli/cmd/newapp.go
Outdated
| } | ||
| case *routeapi.Route: | ||
| if len(t.Spec.Host) > 0 { | ||
| containsRoute = true |
There was a problem hiding this comment.
move containsRoute = true outside the if statement
pkg/oc/cli/cmd/newapp.go
Outdated
| err := wait.PollImmediate(500*time.Millisecond, time.Second*RoutePollTimoutSeconds, func() (bool, error) { | ||
| route, err = config.OSClient.Routes(t.Namespace).Get(t.Name, metav1.GetOptions{}) | ||
| if err != nil { | ||
| return false, coreerror.New(fmt.Sprintf("Error while polling route %s", t.Name)) |
There was a problem hiding this comment.
fyi: fmt.Errorf == errors.New(fmt.Sprintf(...))
but here, just return the error without wrapping it -- you're wrapping it in line 398
0fbc994 to
9ef1268
Compare
|
/approve |
|
/lgtm |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bparees, jim-minter, mangirdaz The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
|
Automatic merge from submit-queue |
Story: https://trello.com/c/Ve6T2QUL/1336-create-routes-from-oc-new-app-appcreation
Comments more than welcome as I'm not familiar with the codebase.