pkg/cmd/cli/cmd/create/route.go
25c24210
 package create
a555a357
 
 import (
 	"fmt"
 	"io"
 
 	"github.com/spf13/cobra"
 
 	kapi "k8s.io/kubernetes/pkg/api"
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 	"k8s.io/kubernetes/pkg/kubectl/resource"
 
6267dded
 	"github.com/openshift/origin/pkg/cmd/templates"
a555a357
 	cmdutil "github.com/openshift/origin/pkg/cmd/util"
 	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
 	"github.com/openshift/origin/pkg/route/api"
 	fileutil "github.com/openshift/origin/pkg/util/file"
 )
 
6267dded
 var (
 	routeLong = templates.LongDesc(`
 		Expose containers externally via secured routes
a555a357
 
6267dded
 		Three types of secured routes are supported: edge, passthrough, and reencrypt.
 		If you wish to create unsecured routes, see "%[1]s expose -h"`)
a555a357
 )
 
 // NewCmdCreateRoute is a macro command to create a secured route.
 func NewCmdCreateRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "route",
 		Short: "Expose containers externally via secured routes",
 		Long:  fmt.Sprintf(routeLong, fullName),
 		Run:   cmdutil.DefaultSubCommandRun(out),
 	}
 
 	cmd.AddCommand(NewCmdCreateEdgeRoute(fullName, f, out))
 	cmd.AddCommand(NewCmdCreatePassthroughRoute(fullName, f, out))
 	cmd.AddCommand(NewCmdCreateReencryptRoute(fullName, f, out))
 
 	return cmd
 }
 
6267dded
 var (
 	edgeRouteLong = templates.LongDesc(`
 		Create a route that uses edge TLS termination
a555a357
 
6267dded
 		Specify the service (either just its name or using type/name syntax) that the
 		generated route should expose via the --service flag.`)
a555a357
 
6267dded
 	edgeRouteExample = templates.Examples(`
 		# Create an edge route named "my-route" that exposes frontend service.
 	  %[1]s create route edge my-route --service=frontend
a555a357
 
6267dded
 	  # Create an edge route that exposes the frontend service and specify a path.
 	  # If the route name is omitted, the service name will be re-used.
 	  %[1]s create route edge --service=frontend --path /assets`)
a555a357
 )
 
 // NewCmdCreateEdgeRoute is a macro command to create an edge route.
 func NewCmdCreateEdgeRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "edge [NAME] --service=SERVICE",
 		Short:   "Create a route that uses edge TLS termination",
 		Long:    edgeRouteLong,
 		Example: fmt.Sprintf(edgeRouteExample, fullName),
 		Run: func(cmd *cobra.Command, args []string) {
 			err := CreateEdgeRoute(f, out, cmd, args)
 			kcmdutil.CheckErr(err)
 		},
 	}
 
 	kcmdutil.AddValidateFlags(cmd)
 	kcmdutil.AddOutputFlagsForMutation(cmd)
 	cmd.Flags().String("hostname", "", "Set a hostname for the new route")
 	cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to")
f89940da
 	cmd.Flags().String("insecure-policy", "", "Set an insecure policy for the new route")
a555a357
 	cmd.Flags().String("service", "", "Name of the service that the new route is exposing")
 	cmd.MarkFlagRequired("service")
 	cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.")
 	cmd.Flags().String("cert", "", "Path to a certificate file.")
a166f955
 	cmd.MarkFlagFilename("cert")
a555a357
 	cmd.Flags().String("key", "", "Path to a key file.")
a166f955
 	cmd.MarkFlagFilename("key")
a555a357
 	cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.")
a166f955
 	cmd.MarkFlagFilename("ca-cert")
a555a357
 
 	return cmd
 }
 
 // CreateEdgeRoute implements the behavior to run the create edge route command.
 func CreateEdgeRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 	oc, kc, err := f.Clients()
 	if err != nil {
 		return err
 	}
 	ns, _, err := f.DefaultNamespace()
 	if err != nil {
 		return err
 	}
 	serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service"))
 	if err != nil {
 		return err
 	}
 	routeName, err := resolveRouteName(args)
 	if err != nil {
 		return err
 	}
396b9eb1
 	route, err := cmdutil.UnsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port"))
a555a357
 	if err != nil {
 		return err
 	}
 
 	route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname")
 	route.Spec.Path = kcmdutil.GetFlagString(cmd, "path")
 
 	route.Spec.TLS = new(api.TLSConfig)
 	route.Spec.TLS.Termination = api.TLSTerminationEdge
 	cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.Certificate = string(cert)
 	key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.Key = string(key)
 	caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.CACertificate = string(caCert)
 
f89940da
 	insecurePolicy := kcmdutil.GetFlagString(cmd, "insecure-policy")
 	if len(insecurePolicy) > 0 {
 		route.Spec.TLS.InsecureEdgeTerminationPolicy = api.InsecureEdgeTerminationPolicyType(insecurePolicy)
 	}
 
a555a357
 	route, err = oc.Routes(ns).Create(route)
 	if err != nil {
 		return err
 	}
59e6f9d2
 	mapper, typer := f.Object(false)
a555a357
 	resourceMapper := &resource.Mapper{
 		ObjectTyper:  typer,
 		RESTMapper:   mapper,
43ba781b
 		ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
a555a357
 	}
997787d8
 	info, err := resourceMapper.InfoForObject(route, nil)
a555a357
 	if err != nil {
 		return err
 	}
 	shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name"
 	kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created")
 	return nil
 }
 
6267dded
 var (
 	passthroughRouteLong = templates.LongDesc(`
 		Create a route that uses passthrough TLS termination
a555a357
 
6267dded
 		Specify the service (either just its name or using type/name syntax) that the
 		generated route should expose via the --service flag.`)
a555a357
 
6267dded
 	passthroughRouteExample = templates.Examples(`
 		# Create a passthrough route named "my-route" that exposes the frontend service.
 	  %[1]s create route passthrough my-route --service=frontend
a555a357
 
6267dded
 	  # Create a passthrough route that exposes the frontend service and specify
 	  # a hostname. If the route name is omitted, the service name will be re-used.
 	  %[1]s create route passthrough --service=frontend --hostname=www.example.com`)
a555a357
 )
 
 // NewCmdCreatePassthroughRoute is a macro command to create a passthrough route.
 func NewCmdCreatePassthroughRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "passthrough [NAME] --service=SERVICE",
 		Short:   "Create a route that uses passthrough TLS termination",
 		Long:    passthroughRouteLong,
 		Example: fmt.Sprintf(passthroughRouteExample, fullName),
 		Run: func(cmd *cobra.Command, args []string) {
 			err := CreatePassthroughRoute(f, out, cmd, args)
 			kcmdutil.CheckErr(err)
 		},
 	}
 
 	kcmdutil.AddValidateFlags(cmd)
 	kcmdutil.AddOutputFlagsForMutation(cmd)
 	cmd.Flags().String("hostname", "", "Set a hostname for the new route")
 	cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to")
 	cmd.Flags().String("service", "", "Name of the service that the new route is exposing")
 	cmd.MarkFlagRequired("service")
 
 	return cmd
 }
 
 // CreatePassthroughRoute implements the behavior to run the create passthrough route command.
 func CreatePassthroughRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 	oc, kc, err := f.Clients()
 	if err != nil {
 		return err
 	}
 	ns, _, err := f.DefaultNamespace()
 	if err != nil {
 		return err
 	}
 	serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service"))
 	if err != nil {
 		return err
 	}
 	routeName, err := resolveRouteName(args)
 	if err != nil {
 		return err
 	}
396b9eb1
 	route, err := cmdutil.UnsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port"))
a555a357
 	if err != nil {
 		return err
 	}
 
 	route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname")
 
 	route.Spec.TLS = new(api.TLSConfig)
 	route.Spec.TLS.Termination = api.TLSTerminationPassthrough
 
 	route, err = oc.Routes(ns).Create(route)
 	if err != nil {
 		return err
 	}
59e6f9d2
 	mapper, typer := f.Object(false)
a555a357
 	resourceMapper := &resource.Mapper{
 		ObjectTyper:  typer,
 		RESTMapper:   mapper,
43ba781b
 		ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
a555a357
 	}
997787d8
 	info, err := resourceMapper.InfoForObject(route, nil)
a555a357
 	if err != nil {
 		return err
 	}
 	shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name"
 	kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created")
 	return nil
 }
 
6267dded
 var (
 	reencryptRouteLong = templates.LongDesc(`
 		Create a route that uses reencrypt TLS termination
a555a357
 
6267dded
 		Specify the service (either just its name or using type/name syntax) that the
 		generated route should expose via the --service flag. A destination CA certificate
 		is needed for reencrypt routes, specify one with the --dest-ca-cert flag.`)
a555a357
 
6267dded
 	reencryptRouteExample = templates.Examples(`
 		# Create a route named "my-route" that exposes the frontend service.
 	  %[1]s create route reencrypt my-route --service=frontend --dest-ca-cert cert.cert
a555a357
 
6267dded
 	  # Create a reencrypt route that exposes the frontend service and re-use
 	  # the service name as the route name.
 	  %[1]s create route reencrypt --service=frontend --dest-ca-cert cert.cert`)
a555a357
 )
 
 // NewCmdCreateReencryptRoute is a macro command to create a reencrypt route.
 func NewCmdCreateReencryptRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:     "reencrypt [NAME] --dest-ca-cert=FILENAME --service=SERVICE",
 		Short:   "Create a route that uses reencrypt TLS termination",
 		Long:    reencryptRouteLong,
 		Example: fmt.Sprintf(reencryptRouteExample, fullName),
 		Run: func(cmd *cobra.Command, args []string) {
 			err := CreateReencryptRoute(f, out, cmd, args)
 			kcmdutil.CheckErr(err)
 		},
 	}
 
 	kcmdutil.AddValidateFlags(cmd)
 	kcmdutil.AddOutputFlagsForMutation(cmd)
 	cmd.Flags().String("hostname", "", "Set a hostname for the new route")
 	cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to")
 	cmd.Flags().String("service", "", "Name of the service that the new route is exposing")
 	cmd.MarkFlagRequired("service")
 	cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.")
 	cmd.Flags().String("cert", "", "Path to a certificate file.")
a166f955
 	cmd.MarkFlagFilename("cert")
a555a357
 	cmd.Flags().String("key", "", "Path to a key file.")
a166f955
 	cmd.MarkFlagFilename("key")
a555a357
 	cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.")
a166f955
 	cmd.MarkFlagFilename("ca-cert")
a555a357
 	cmd.Flags().String("dest-ca-cert", "", "Path to a CA certificate file, used for securing the connection from the router to the destination.")
 	cmd.MarkFlagRequired("dest-ca-cert")
a166f955
 	cmd.MarkFlagFilename("dest-ca-cert")
a555a357
 
 	return cmd
 }
 
 // CreateReencryptRoute implements the behavior to run the create reencrypt route command.
 func CreateReencryptRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
 	oc, kc, err := f.Clients()
 	if err != nil {
 		return err
 	}
 	ns, _, err := f.DefaultNamespace()
 	if err != nil {
 		return err
 	}
 	serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service"))
 	if err != nil {
 		return err
 	}
 	routeName, err := resolveRouteName(args)
 	if err != nil {
 		return err
 	}
396b9eb1
 	route, err := cmdutil.UnsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port"))
a555a357
 	if err != nil {
 		return err
 	}
 
 	route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname")
 	route.Spec.Path = kcmdutil.GetFlagString(cmd, "path")
 
 	route.Spec.TLS = new(api.TLSConfig)
a38817a1
 	route.Spec.TLS.Termination = api.TLSTerminationReencrypt
a555a357
 
 	cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.Certificate = string(cert)
 	key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.Key = string(key)
 	caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.CACertificate = string(caCert)
 	destCACert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "dest-ca-cert"))
 	if err != nil {
 		return err
 	}
 	route.Spec.TLS.DestinationCACertificate = string(destCACert)
 
 	route, err = oc.Routes(ns).Create(route)
 	if err != nil {
 		return err
 	}
59e6f9d2
 	mapper, typer := f.Object(false)
a555a357
 	resourceMapper := &resource.Mapper{
 		ObjectTyper:  typer,
 		RESTMapper:   mapper,
43ba781b
 		ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
a555a357
 	}
997787d8
 	info, err := resourceMapper.InfoForObject(route, nil)
a555a357
 	if err != nil {
 		return err
 	}
 	shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name"
 	kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created")
 	return nil
 }
 
 func resolveServiceName(f *clientcmd.Factory, resource string) (string, error) {
 	if len(resource) == 0 {
 		return "", fmt.Errorf("you need to provide a service name via --service")
 	}
59e6f9d2
 	mapper, _ := f.Object(false)
49ad7ccd
 	rType, name, err := cmdutil.ResolveResource(kapi.Resource("services"), resource, mapper)
a555a357
 	if err != nil {
 		return "", err
 	}
49ad7ccd
 	if rType != kapi.Resource("services") {
 		return "", fmt.Errorf("cannot expose %v as routes", rType)
a555a357
 	}
 	return name, nil
 }
 
 func resolveRouteName(args []string) (string, error) {
 	switch len(args) {
 	case 0:
 	case 1:
 		return args[0], nil
 	default:
 		return "", fmt.Errorf("multiple names provided. Please specify at most one")
 	}
 	return "", nil
 }