-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Route creation with oc new-app #16396
Route creation with oc new-app #16396
Conversation
/unassign @smarterclayton |
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.
Great start @mangirdaz!
pkg/template/controller/readiness.go
Outdated
@@ -133,6 +134,15 @@ func checkStatefulSetReadiness(oc client.Interface, obj runtime.Object) (bool, b | |||
return ready, failed, nil | |||
} | |||
|
|||
// checkRouteReadiness checks if host fiels was prepoplated already. |
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/fiels/field/
s/prepoplated/prepopulated/
pkg/template/controller/readiness.go
Outdated
@@ -133,6 +134,15 @@ func checkStatefulSetReadiness(oc client.Interface, obj runtime.Object) (bool, b | |||
return ready, failed, nil | |||
} | |||
|
|||
// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
@@ -146,6 +156,7 @@ var readinessCheckers = map[schema.GroupKind]func(client.Interface, runtime.Obje | |||
deployapi.Kind("DeploymentConfig"): checkDeploymentConfigReadiness, | |||
batch.Kind("Job"): checkJobReadiness, | |||
apps.Kind("StatefulSet"): checkStatefulSetReadiness, | |||
routeapi.Kind("Route"): checkRouteReadiness, |
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.
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
@@ -373,6 +374,10 @@ func (o *NewAppOptions) RunNewApp() error { | |||
hasMissingRepo = true | |||
fmt.Fprintf(out, "%sWARNING: No Docker registry has been configured with the server. Automatic builds and deployments may not function.\n", indent) | |||
} | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/The Access application/Access your app/
pkg/oc/cli/cmd/newapp.go
Outdated
fmt.Fprintf(out, "%sRun '%s %s' to view your app.\n", indent, o.BaseName, StatusRecommendedName) | ||
} | ||
return nil | ||
} | ||
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func getServices(items []runtime.Object) []*kapi.Service
would be a better signature
pkg/oc/cli/cmd/newapp.go
Outdated
@@ -385,13 +390,45 @@ func (o *NewAppOptions) RunNewApp() error { | |||
fmt.Fprintf(out, "%sTrack installation of %s with '%s logs %s'.\n", indent, installing[i].Name, o.BaseName, installing[i].Name) | |||
} | |||
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 |
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.
spelling
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to change it, but for reference, you can also do if s, ok := i.(*kapi.Service); ok { svc = append(svc, s) }
test/cmd/newapp.sh
Outdated
@@ -36,6 +36,8 @@ os::cmd::expect_success_and_text 'oc new-app mysql --dry-run' 'tag "5.7" for "my | |||
# 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
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.
done.
/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
@@ -373,6 +374,10 @@ func (o *NewAppOptions) RunNewApp() error { | |||
hasMissingRepo = true | |||
fmt.Fprintf(out, "%sWARNING: No Docker registry has been configured with the server. Automatic builds and deployments may not function.\n", indent) | |||
} | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes i think a cap on how long to wait is a good idea.
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check out wait.Poll as it's used elsewhere in the codebase.
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.
done
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 |
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/compltd/completed/
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be return false, 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.
Done.
3a64066
to
0fbc994
Compare
lgtm. @smarterclayton any final concerns? |
pkg/oc/cli/cmd/newapp.go
Outdated
"github.com/openshift/origin/pkg/util" | ||
) | ||
|
||
// NewAppRecommendedCommandName is the recommended command name. | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const RoutePollTimeout = 5 * time.Second
pkg/oc/cli/cmd/newapp.go
Outdated
@@ -2,6 +2,7 @@ package cmd | |||
|
|||
import ( | |||
"bytes" | |||
coreerror "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.
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
@@ -373,6 +379,27 @@ func (o *NewAppOptions) RunNewApp() error { | |||
hasMissingRepo = true | |||
fmt.Fprintf(out, "%sWARNING: No Docker registry has been configured with the server. Automatic builds and deployments may not function.\n", indent) | |||
} | |||
case *routeapi.Route: | |||
if len(t.Spec.Host) > 0 { | |||
containsRoute = true |
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi: fmt.Errorf == errors.New(fmt.Sprintf(...))
but here, just return the error without wrapping it -- you're wrapping it in line 398
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.
done
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.
Needs 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.