Skip to content

Commit

Permalink
oc new-app expose message logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mjudeikis committed Sep 21, 2017
1 parent 97f4072 commit 3a64066
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
49 changes: 49 additions & 0 deletions pkg/oc/cli/cmd/newapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"bytes"
coreerror "errors"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -40,12 +41,16 @@ import (
newcmd "github.com/openshift/origin/pkg/generate/app/cmd"
"github.com/openshift/origin/pkg/generate/git"
imageapi "github.com/openshift/origin/pkg/image/apis/image"
routeapi "github.com/openshift/origin/pkg/route/apis/route"
"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

var (
newAppLong = templates.LongDesc(`
Create a new application by specifying source code, templates, and/or images
Expand Down Expand Up @@ -345,6 +350,7 @@ func (o *NewAppOptions) RunNewApp() error {
hasMissingRepo := false
installing := []*kapi.Pod{}
indent := o.Action.DefaultIndent()
containsRoute := false
for _, item := range result.List.Items {
switch t := item.(type) {
case *kapi.Pod:
Expand Down Expand Up @@ -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
var route *routeapi.Route
//check if route processing was complted and host field is prepopulated by router
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))
}
if route.Spec.Host != "" {
return true, nil
}
return false, coreerror.New(fmt.Sprintf("Timout while polling route %s", t.Name))
})
if err != nil {
glog.V(4).Infof("Failed to poll route %s host field: %v", t.Name, err)
} else {
fmt.Fprintf(out, "%sAccess your application via route '%s' \n", indent, route.Spec.Host)
}
}
}
}

Expand All @@ -385,13 +412,35 @@ 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 don't find a route we give a message to expose it
if !containsRoute {
//we if don't have any routes, but we have services - we suggest commands to expose those
svc := getServices(result.List.Items)
if len(svc) > 0 {
fmt.Fprintf(out, "%sApplication is not exposed. You can expose services to the outside world by executing one or more of the commands below:\n", indent)
for _, s := range svc {
fmt.Fprintf(out, "%s '%s %s svc/%s' \n", indent, o.BaseName, ExposeRecommendedName, s.Name)
}
}
}
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 getServices(items []runtime.Object) []*kapi.Service {
var svc []*kapi.Service
for _, i := range items {
switch i.(type) {
case *kapi.Service:
svc = append(svc, i.(*kapi.Service))
}
}
return svc
}

func followInstallation(config *newcmd.AppConfig, input string, pod *kapi.Pod, logsForObjectFn LogsForObjectFunc) error {
fmt.Fprintf(config.Out, "--> Installing ...\n")

Expand Down
3 changes: 3 additions & 0 deletions pkg/oc/cli/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
// StatusRecommendedName is the recommended command name.
const StatusRecommendedName = "status"

// ExposeRecommendedName is the recommended command name to expose app.
const ExposeRecommendedName = "expose"

var (
statusLong = templates.LongDesc(`
Show a high level overview of the current project
Expand Down
12 changes: 12 additions & 0 deletions pkg/template/controller/readiness.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
buildapi "github.com/openshift/origin/pkg/build/apis/build"
buildutil "github.com/openshift/origin/pkg/build/util"
"github.com/openshift/origin/pkg/client"
routeapi "github.com/openshift/origin/pkg/route/apis/route"
)

// checkBuildReadiness determins if a Build is ready, failed or neither.
Expand Down Expand Up @@ -133,6 +134,15 @@ func checkStatefulSetReadiness(oc client.Interface, obj runtime.Object) (bool, b
return ready, failed, nil
}

// checkRouteReadiness checks if host field was prepopulated already.
func checkRouteReadiness(oc client.Interface, obj runtime.Object) (bool, bool, error) {
route := obj.(*routeapi.Route)
ready := route.Spec.Host != ""
failed := false

return ready, failed, nil
}

// readinessCheckers maps GroupKinds to the appropriate function. Note that in
// some cases more than one GK maps to the same function.
var readinessCheckers = map[schema.GroupKind]func(client.Interface, runtime.Object) (bool, bool, error){
Expand All @@ -146,6 +156,8 @@ 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,
routeapi.LegacyKind("Route"): checkRouteReadiness,
}

// canCheckReadiness indicates whether a readiness check exists for a GK.
Expand Down
37 changes: 37 additions & 0 deletions pkg/template/controller/readiness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
deployapi "github.com/openshift/origin/pkg/apps/apis/apps"
buildapi "github.com/openshift/origin/pkg/build/apis/build"
"github.com/openshift/origin/pkg/client/testclient"
routeapi "github.com/openshift/origin/pkg/route/apis/route"
)

func TestCheckReadiness(t *testing.T) {
Expand Down Expand Up @@ -224,6 +225,42 @@ func TestCheckReadiness(t *testing.T) {
},
expectedReady: true,
},
{
groupKind: routeapi.Kind("Route"),
object: &routeapi.Route{
Spec: routeapi.RouteSpec{
Host: "",
},
},
expectedReady: false,
},
{
groupKind: routeapi.Kind("Route"),
object: &routeapi.Route{
Spec: routeapi.RouteSpec{
Host: "app.example.com",
},
},
expectedReady: true,
},
{
groupKind: routeapi.LegacyKind("Route"),
object: &routeapi.Route{
Spec: routeapi.RouteSpec{
Host: "",
},
},
expectedReady: false,
},
{
groupKind: routeapi.LegacyKind("Route"),
object: &routeapi.Route{
Spec: routeapi.RouteSpec{
Host: "app.example.com",
},
},
expectedReady: true,
},
}

for i, test := range tests {
Expand Down
4 changes: 4 additions & 0 deletions test/cmd/newapp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ 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 test/testdata/template-minimal-expose.json --as-test' 'Access your application via route'
os::cmd::expect_success 'oc delete all -l app=expose-output'
os::cmd::expect_success_and_text 'oc new-app mysql --as-test' 'Application is not exposed'
os::cmd::expect_success 'oc delete all -l app=mysql'

# test that imagestream references across imagestreams do not cause an error
os::cmd::try_until_success 'oc get imagestreamtags ruby:2.3'
Expand Down
60 changes: 60 additions & 0 deletions test/testdata/template-minimal-expose.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "helloworld-sample"
},
"objects": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "frontend"
},
"spec": {
"ports": [
{
"name": "web",
"protocol": "TCP",
"port": 5432,
"targetPort": 8080,
"nodePort": 0
}
],
"selector": {
"name": "frontend"
},
"type": "ClusterIP",
"sessionAffinity": "None"
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "route-edge",
"annotations": {
"template.openshift.io/expose-uri": "http://{.spec.host}{.spec.path}"
}
},
"spec": {
"host": "www.example.com",
"to": {
"kind": "Service",
"name": "frontend"
},
"tls": {
"termination": "edge"
}
},
"status": {}
}
],
"parameters": [],
"labels": {
"app": "expose-output"
}
}

0 comments on commit 3a64066

Please sign in to comment.