diff --git a/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/helper.go b/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/helper.go index 059cce16ebe9..f6ba84d52400 100644 --- a/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/helper.go +++ b/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/helper.go @@ -18,7 +18,6 @@ package client import ( "fmt" - "io/ioutil" "net/http" "net/url" "os" @@ -266,19 +265,6 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip return rt, nil } -// dataFromSliceOrFile returns data from the slice (if non-empty), or from the file, -// or an error if an error occurred reading the file -func dataFromSliceOrFile(data []byte, file string) ([]byte, error) { - if len(data) > 0 { - return data, nil - } - fileData, err := ioutil.ReadFile(file) - if err != nil { - return []byte{}, err - } - return fileData, nil -} - // DefaultServerURL converts a host, host:port, or URL string to the default base server API path // to use with a Client at a given API version following the standard conventions for a // Kubernetes API. diff --git a/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/transport.go b/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/transport.go index 62dd09648721..22278c4481ed 100644 --- a/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/transport.go +++ b/Godeps/_workspace/src/github.com/GoogleCloudPlatform/kubernetes/pkg/client/transport.go @@ -20,6 +20,7 @@ import ( "crypto/tls" "crypto/x509" "fmt" + "io/ioutil" "net/http" ) @@ -81,32 +82,19 @@ func TLSConfigFor(config *Config) (*tls.Config, error) { if hasCA && config.Insecure { return nil, fmt.Errorf("specifying a root certificates file with the insecure flag is not allowed") } + if err := LoadTLSFiles(config); err != nil { + return nil, err + } var tlsConfig *tls.Config switch { case hasCert: - certData, err := dataFromSliceOrFile(config.CertData, config.CertFile) - if err != nil { - return nil, err - } - keyData, err := dataFromSliceOrFile(config.KeyData, config.KeyFile) - if err != nil { - return nil, err - } - caData, err := dataFromSliceOrFile(config.CAData, config.CAFile) - if err != nil { - return nil, err - } - cfg, err := NewClientCertTLSConfig(certData, keyData, caData) + cfg, err := NewClientCertTLSConfig(config.CertData, config.KeyData, config.CAData) if err != nil { return nil, err } tlsConfig = cfg case hasCA: - caData, err := dataFromSliceOrFile(config.CAData, config.CAFile) - if err != nil { - return nil, err - } - cfg, err := NewTLSConfig(caData) + cfg, err := NewTLSConfig(config.CAData) if err != nil { return nil, err } @@ -118,6 +106,45 @@ func TLSConfigFor(config *Config) (*tls.Config, error) { return tlsConfig, nil } +// LoadTLSFiles copies the data from the CertFile, KeyFile, and CAFile fields into the CertData, +// KeyData, and CAFile fields, or returns an error. If no error is returned, all three fields are +// either populated or were empty to start. +func LoadTLSFiles(config *Config) error { + certData, err := dataFromSliceOrFile(config.CertData, config.CertFile) + if err != nil { + return err + } + config.CertData = certData + keyData, err := dataFromSliceOrFile(config.KeyData, config.KeyFile) + if err != nil { + return err + } + config.KeyData = keyData + caData, err := dataFromSliceOrFile(config.CAData, config.CAFile) + if err != nil { + return err + } + config.CAData = caData + + return nil +} + +// dataFromSliceOrFile returns data from the slice (if non-empty), or from the file, +// or an error if an error occurred reading the file +func dataFromSliceOrFile(data []byte, file string) ([]byte, error) { + if len(data) > 0 { + return data, nil + } + if len(file) > 0 { + fileData, err := ioutil.ReadFile(file) + if err != nil { + return []byte{}, err + } + return fileData, nil + } + return nil, nil +} + func NewClientCertTLSConfig(certData, keyData, caData []byte) (*tls.Config, error) { cert, err := tls.X509KeyPair(certData, keyData) if err != nil { diff --git a/docs/routing.md b/docs/routing.md index 7a9e2995541d..8cdffa2c40b9 100644 --- a/docs/routing.md +++ b/docs/routing.md @@ -32,12 +32,10 @@ Once it is pulled it will start and be visible in the `docker ps` list of contai [vagrant@openshiftdev origin]$ sudo /data/src/github.com/openshift/origin/_output/local/bin/linux/amd64/openshift start & If running in https mode, ensure osc can authenticate to the master - [vagrant@openshiftdev origin]$ export KUBECONFIG=/data/src/github.com/openshift/origin/openshift.local.certificates/admin/.kubeconfig + [vagrant@openshiftdev origin]$ export KUBECONFIG=/data/src/github.com/openshift/origin/openshift.local.certificates/openshift-client/.kubeconfig [vagrant@openshiftdev origin]$ sudo chmod a+r "$KUBECONFIG" - - If running in https mode, ensure install-router.sh can authenticate to the master [vagrant@openshiftdev origin]$ sudo chmod a+r openshift.local.certificates/openshift-client/key.key - [vagrant@openshiftdev origin]$ CERT_DIR=openshift.local.certificates/openshift-client hack/install-router.sh {router_id} {master_url} + [vagrant@openshiftdev origin]$ openshift ex router --create --credentials="${KUBECONFIG}" [vagrant@openshiftdev origin]$ osc get pods #### Clustered vagrant environment @@ -46,7 +44,7 @@ Once it is pulled it will start and be visible in the `docker ps` list of contai $ export OPENSHIFT_DEV_CLUSTER=true $ vagrant up $ vagrant ssh master - [vagrant@openshift-master ~]$ hack/install-router.sh {router_id} {master_url} + [vagrant@openshift-master ~]$ openshift ex router --create --credentials="${KUBECONFIG}" @@ -58,12 +56,14 @@ In order to run the router in a deployed environment the following conditions mu * The machine may or may not be registered with the master. Optimally it will not serve pods while also serving as the router * The machine must not have services running on it that bind to host port 80 since this is what the router uses for traffic -To install the router pod you use the `hack/install-router.sh` script, passing it the router id, master url, and, optionally, -the OpenShift executable. If the executable is not passed the script will try to find it via the `PATH`. If the -script is still unable to find the OpenShift executable then it will simply create the `/tmp/router.json` file and stop. -It is then up to the user to issue the `osc create` command manually. +To install the router pod you use the `openshift ex router` command line, passing the flags `--create` and `--credentials=`. +The credentials flag controls the identity that the router will use to talk to the master (and the address of the master) so in most +environments you can use the `${CERTS_DIR}/openshift-client/.kubeconfig` file. Once you run this command you can check the configuration +of the router by running `osc get dc router` to check the deployment status. + +`openshift ex router` offers other options for deploying routers - run `openshift help ex router` for more details. -### Manually +### Manually To run the router manually (outside of a pod) you should first build the images with instructions found below. Then you can run the router anywhere that it can access both the pods and the master. The router exposes port 80 so the host diff --git a/examples/sample-app/README.md b/examples/sample-app/README.md index d76ec4b9966d..661d39e048a7 100644 --- a/examples/sample-app/README.md +++ b/examples/sample-app/README.md @@ -93,10 +93,10 @@ the present working directory is the same directory as this README. need to accept the server certificates and present its own client certificate. These are generated as part of the `openshift start` command in whatever the current directory is at the time. You will - need to point osc and curl at the appropriate .kubeconfig in order - to connect to OpenShift. Assuming you are running as a user other - than root, you will also need to make the .kubeconfig readable by - that user. (Note: this is just for example purposes; in a real + need to point osc and curl at the appropriate .kubeconfig in order + to connect to OpenShift. Assuming you are running as a user other + than root, you will also need to make the .kubeconfig readable by + that user. (Note: this is just for example purposes; in a real installation, users would generate their own keys and not have access to the system keys.) @@ -285,7 +285,7 @@ Congratulations, you've successfully deployed and updated an application on Open Advanced --------- -OpenShift also provides features that live outside the deployment life cycle like routing. +OpenShift also provides features that live outside the deployment life cycle like routing. 1. Your sample app has been created with a secure route which can be viewed by performing a `GET` on the route api object. @@ -295,53 +295,47 @@ OpenShift also provides features that live outside the deployment life cycle lik 2. To use the route you must first install a router. OpenShift provides an HAProxy router implementation that we'll use. -To install the router you must know the ip address of the host the router will be deployed on (used later) and the api +To install the router you must know the ip address of the host the router will be deployed on (used later) and the api url the master is listening on. The api url can be found in the logs, your ip address can be determined with `ip a`. Replace the ip address shown below with the correct one for your environment. - # Optional: pre-pull the router image. This will be pulled automatically when the pod is created but will - # take some time. Your pod will stay in Pending state while the pull is completed + # Optional: pre-pull the router image. This will be pulled automatically when the pod is created but will + # take some time. Your pod will stay in Pending state while the pull is completed $ docker pull openshift/origin-haproxy-router - - $ pushd ../.. - $ sudo chmod +r ./openshift.local.certificates/openshift-client/key.key - $ CERT_DIR=openshift.local.certificates/openshift-client hack/install-router.sh router https://10.0.2.15:8443 - Creating router file and starting pod... - router - $ popd + + $ openshift ex router --create --credentials="${KUBECONFIG}" + router # the service + router # the deployment config 3. Wait for the router to start. - $ osc get pods - POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS - docker-registry-1-fnd84 172.17.0.3 registry-container openshift/docker-registry openshiftdev.local/127.0.0.1 deployment=docker-registry-1,deploymentconfig=docker-registry,name=registrypod,template=docker-registry-template Running - router 172.17.0.10 origin-haproxy-router-router openshift/origin-haproxy-router openshiftdev.local/127.0.0.1 Running + $ osc describe dc router + # watch for the number of deployed pods to go to 1 4. *Optional:* View the logs of the router. - - $ osc log router + $ osc log router-1- 5. Curl the url, substituting the ip address shown for the correct value in your environment. - $ curl -s -k --resolve www.example.com:443:10.0.2.15 https://www.example.com - ... removed for readability ... + $ curl -s -k --resolve www.example.com:443:10.0.2.15 https://www.example.com + ... removed for readability ... Hello from OpenShift v3! ... removed for readability ... - + 7. *Optional*: View the certificate being used for the secure route. - + $ openssl s_client -servername www.example.com -connect 10.0.2.15:443 ... removed for readability ... subject=/CN=www.example.com/ST=SC/C=US/emailAddress=example@example.com/O=Example/OU=Example issuer=/C=US/ST=SC/L=Default City/O=Default Company Ltd/OU=Test CA/CN=www.exampleca.com/emailAddress=example@example.com ... removed for readability ... ^C - + Additional Operations diff --git a/hack/install-router.sh b/hack/install-router.sh deleted file mode 100755 index a05fb0e8053a..000000000000 --- a/hack/install-router.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -set -e - -# ID to be used as the k8s id and also appended to the container name. Defaults to router1 -ROUTER_ID="${1}" -# Full address to connect to the master. -MASTER_URL="${2}" -# openshift executable - optional, will try to find it on the path if not specified -OPENSHIFT="${3}" - -OS_ROOT=$(dirname "${BASH_SOURCE}")/.. - -if [[ "${ROUTER_ID}" == "" ]]; then - echo "No router id provided, cannot create router..." - exit -fi - -if [[ "${MASTER_URL}" == "" ]]; then - echo "No master url provided, cannot create router..." - exit -fi -if [[ "${MASTER_URL}" != "http"* ]]; then - echo "Master url must include protocol, e.g. https://localhost:8443" - exit -fi - -if [[ "${OPENSHIFT}" == "" ]]; then - if [[ "$(which osc)" != "" ]]; then - OPENSHIFT=$(which osc) - fi -fi - -OPENSHIFT_INSECURE="${OPENSHIFT_INSECURE:-false}" -CERT_DIR="${CERT_DIR:-}" -OPENSHIFT_CA_DATA="${OPENSHIFT_CA_DATA:-}" -OPENSHIFT_CERT_DATA="${OPENSHIFT_CERT_DATA:-}" -OPENSHIFT_KEY_DATA="${OPENSHIFT_KEY_DATA:-}" - -if [[ "${MASTER_URL}" == "https"* ]]; then - # Read client cert data in to send to containerized components - if [ -n "${CERT_DIR}" ]; then - OPENSHIFT_CA_DATA="$(cat "${CERT_DIR}/root.crt")" - OPENSHIFT_CERT_DATA="$(cat "${CERT_DIR}/cert.crt")" - OPENSHIFT_KEY_DATA="$(cat "${CERT_DIR}/key.key")" - fi - - # I don't know how to do this inline with bash and it's logically a separate step we want to remove anyway - # TODO: remove this once services can provide root cert data to pods - # Escape cert data for json - OPENSHIFT_CA_DATA="${OPENSHIFT_CA_DATA//$'\n'/\\\\n}" - OPENSHIFT_CERT_DATA="${OPENSHIFT_CERT_DATA//$'\n'/\\\\n}" - OPENSHIFT_KEY_DATA="${OPENSHIFT_KEY_DATA//$'\n'/\\\\n}" - - - if [[ "$OPENSHIFT_CA_DATA" == "" ]]; then - echo "Running against an HTTPS master (${MASTER_URL}) without a trusted certificate bundle." - echo "Set \$CERT_DIR to the directory containing the root certificate bundle (root.crt), client certificate (cert.crt), and the client key (key.key) to start securely next time." - echo "Starting insecurely..." - OPENSHIFT_INSECURE=true - fi - -else - OPENSHIFT_INSECURE="" - OPENSHIFT_CA_DATA="" - OPENSHIFT_CERT_DATA="" - OPENSHIFT_KEY_DATA="" -fi - -# update the template file -echo "Creating router file and starting pod..." -cp "${OS_ROOT}/images/router/haproxy/pod.json" /tmp/router.json -sed -i "s|ROUTER_ID|${ROUTER_ID}|g" /tmp/router.json -sed -i "s|\${OPENSHIFT_MASTER}|${MASTER_URL}|" /tmp/router.json -sed -i "s|\${OPENSHIFT_INSECURE}|${OPENSHIFT_INSECURE}|" /tmp/router.json -sed -i "s|\${OPENSHIFT_CA_DATA}|${OPENSHIFT_CA_DATA}|" /tmp/router.json -sed -i "s|\${OPENSHIFT_CERT_DATA}|${OPENSHIFT_CERT_DATA}|" /tmp/router.json -sed -i "s|\${OPENSHIFT_KEY_DATA}|${OPENSHIFT_KEY_DATA}|" /tmp/router.json -# TODO: provide security context to client inside router pod - -# create the pod if we can find openshift -if [ "${OPENSHIFT}" == "" ]; then - echo "Unable to find openshift binary" - echo "/tmp/router.json has been created. In order to start the router please run:" - echo "osc create -f /tmp/router.json" -else - "${OPENSHIFT}" --server="${MASTER_URL}" create -f /tmp/router.json -fi diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 3ede94d2a634..4035762090bf 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -234,16 +234,13 @@ echo "start-build: ok" osc describe build ${started} | grep openshift/ruby-20-centos$ osc cancel-build "${started}" --dump-logs --restart -echo "cancel-build: ok" - # a build for which there is an upstream tag in the corresponding imagerepo, so # the build should use that specific tag of the image instead of the image field # as defined in the buildconfig started=$(osc start-build ruby-sample-build-validtag) osc describe build ${started} | grep openshift/ruby-20-centos:success$ osc cancel-build "${started}" --dump-logs --restart - -osc get minions,pods +echo "cancel-build: ok" openshift ex policy add-group cluster-admin system:unauthenticated openshift ex policy remove-group cluster-admin system:unauthenticated @@ -259,4 +256,12 @@ openshift ex new-project ui-test-project --admin="anypassword:createuser" openshift ex policy add-user admin anypassword:adduser -n ui-test-project osc describe policybinding master -n ui-test-project | grep createuser osc describe policybinding master -n ui-test-project | grep adduser -echo "UI project commands: ok" +echo "ui-project-commands: ok" + +[ ! "$(openshift ex router | grep 'does not exist')"] +[ "$(openshift ex router -o yaml --credentials="${KUBECONFIG}" | grep 'openshift/origin-haproxy-')" ] +openshift ex router --create --credentials="${KUBECONFIG}" +[ "$(openshift ex router | grep 'service exists')" ] +echo "ex router: ok" + +osc get minions,pods diff --git a/hack/test-end-to-end.sh b/hack/test-end-to-end.sh index 2ed099b907db..3a9e3ff2ccc0 100755 --- a/hack/test-end-to-end.sh +++ b/hack/test-end-to-end.sh @@ -209,8 +209,12 @@ openshift ex new-project test --description="This is an example project to demon echo "The console should be available at ${API_SCHEME}://${PUBLIC_MASTER_HOST}:$(($API_PORT + 1)). You may need to visit ${API_SCHEME}://${PUBLIC_MASTER_HOST}:${API_PORT} first to accept the certificate." echo "Log in as 'e2e-user' to see the 'test' project." +# install the router +echo "[INFO] Installing the router" +openshift ex router --create --credentials="${KUBECONFIG}" --images="${USE_IMAGES}" # install the registry +echo "[INFO] Installing the registry" CERT_DIR="${CERT_DIR}/openshift-client" hack/install-registry.sh echo "[INFO] Waiting for Docker registry pod to start" @@ -262,16 +266,8 @@ wait_for_app "test" #wait_for_build "custom" #wait_for_app "custom" -if [[ "$ROUTER_TESTS_ENABLED" == "true" ]]; then - echo "[INFO] Installing router with master url of ${API_SCHEME}://${CONTAINER_ACCESSIBLE_API_HOST}:${API_PORT} and starting pod..." - echo "[INFO] To disable router testing set ROUTER_TESTS_ENABLED=false..." - CERT_DIR="${CERT_DIR}/openshift-client" "${OS_ROOT}/hack/install-router.sh" "router1" "${API_SCHEME}://${CONTAINER_ACCESSIBLE_API_HOST}:${API_PORT}" - wait_for_command "osc get pods | grep router1 | grep -i Running" $((5*TIME_MIN)) - - echo "[INFO] Validating routed app response..." - validate_response "-s -k --resolve www.example.com:443:${CONTAINER_ACCESSIBLE_API_HOST} https://www.example.com" "Hello from OpenShift" 0.2 50 -else - echo "[INFO] Validating app response..." - validate_response "http://${FRONTEND_IP}:5432" "Hello from OpenShift" -fi +# ensure the router is started +wait_for_command "osc get pods | grep router-1 | grep -i Running" $((5*TIME_MIN)) +echo "[INFO] Validating routed app response..." +validate_response "-s -k --resolve www.example.com:443:${CONTAINER_ACCESSIBLE_API_HOST} https://www.example.com" "Hello from OpenShift" 0.2 50 diff --git a/pkg/cmd/experimental/router/router.go b/pkg/cmd/experimental/router/router.go new file mode 100644 index 000000000000..640b5c5459e8 --- /dev/null +++ b/pkg/cmd/experimental/router/router.go @@ -0,0 +1,273 @@ +package router + +import ( + "fmt" + "io" + "os" + "strings" + + kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + kclientcmd "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" + "github.com/golang/glog" + "github.com/spf13/cobra" + + "github.com/openshift/origin/pkg/cmd/util/clientcmd" + "github.com/openshift/origin/pkg/cmd/util/variable" + configcmd "github.com/openshift/origin/pkg/config/cmd" + dapi "github.com/openshift/origin/pkg/deploy/api" + "github.com/openshift/origin/pkg/generate/app" + //imageapi "github.com/openshift/origin/pkg/image/api" +) + +const longDesc = ` +Install or configure an OpenShift router + +This command helps to setup an OpenShift router to take edge traffic and balance it to +your application. With no arguments, the command will check for an existing router +service called 'router' and perform some diagnostics to ensure the router is properly +configured and functioning. + +If a router does not exist with the given name, the --create flag can be passed to +create a deployment configuration and service that will run the router. If you are +running your router in production, you should pass --replicas=2 or higher to ensure +you have failover protection. + +Examples: + Check the default router ("router"): + + $ %[1]s %[2]s + + See what the router would look like if created: + + $ %[1]s %[2]s -o json + + Create a router if it does not exist: + + $ %[1]s %[2]s router-west --create --replicas=2 + + Use a different router image and see the router configuration: + + $ %[1]s %[2]s region-west -o yaml --images=myrepo/somerouter:mytag + +ALPHA: This command is currently being actively developed. It is intended to simplify + the tasks of setting up routers in a new installation. +` + +type config struct { + Type string + ImageTemplate variable.ImageTemplate + Ports string + Replicas int + Labels string + Create bool + Credentials string +} + +const defaultLabel = "router=" + +func NewCmdRouter(f *clientcmd.Factory, parentName, name string, out io.Writer) *cobra.Command { + cfg := &config{ + ImageTemplate: variable.NewDefaultImageTemplate(), + + Labels: defaultLabel, + Ports: "80:80,443:443", + Replicas: 1, + } + + cmd := &cobra.Command{ + Use: fmt.Sprintf("%s []", name), + Short: "Install and check OpenShift routers", + Long: fmt.Sprintf(longDesc, parentName, name), + + Run: func(cmd *cobra.Command, args []string) { + var name string + switch len(args) { + case 0: + name = "router" + case 1: + name = args[0] + default: + glog.Fatalf("You may pass zero or one arguments to provide a name for the router") + } + + ports, err := app.ContainerPortsFromString(cfg.Ports) + if err != nil { + glog.Fatal(err) + } + + label := map[string]string{"router": name} + if cfg.Labels != defaultLabel { + valid, remove, err := app.LabelsFromSpec(strings.Split(cfg.Labels, ",")) + if err != nil { + glog.Fatal(err) + } + if len(remove) > 0 { + glog.Fatalf("You may not pass negative labels in %q", cfg.Labels) + } + label = valid + } + + image := cfg.ImageTemplate.ExpandOrDie(cfg.Type) + + namespace, err := f.OpenShiftClientConfig.Namespace() + if err != nil { + glog.Fatalf("Error getting client: %v", err) + } + _, kClient, err := f.Clients(cmd) + if err != nil { + glog.Fatalf("Error getting client: %v", err) + } + + p, output, err := cmdutil.PrinterForCommand(cmd) + if err != nil { + glog.Fatalf("Unable to configure printer: %v", err) + } + + generate := output + if !generate { + _, err = kClient.Services(namespace).Get(name) + if err != nil { + if !errors.IsNotFound(err) { + glog.Fatalf("Can't check for existing router %q: %v", name, err) + } + generate = true + } + } + + if generate { + if !cfg.Create && !output { + glog.Fatalf("Router %q does not exist (no service). Pass --create to install.", name) + } + + // create new router + if len(cfg.Credentials) == 0 { + glog.Fatalf("You must specify a .kubeconfig file path containing credentials for connecting the router to the master with --credentials") + } + credentials, err := (&kclientcmd.ClientConfigLoadingRules{CommandLinePath: cfg.Credentials}).Load() + if err != nil { + glog.Fatalf("The provided credentials %q could not be loaded: %v", cfg.Credentials, err) + } + config, err := kclientcmd.NewDefaultClientConfig(*credentials, &kclientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + glog.Fatalf("The provided credentials %q could not be used: %v", cfg.Credentials, err) + } + if err := kclient.LoadTLSFiles(config); err != nil { + glog.Fatalf("The provided credentials %q could not load certificate info: %v", cfg.Credentials, err) + } + insecure := "false" + if config.Insecure { + insecure = "true" + } + env := app.Environment{ + "OPENSHIFT_MASTER": config.Host, + "OPENSHIFT_CA_DATA": string(config.CAData), + "OPENSHIFT_KEY_DATA": string(config.KeyData), + "OPENSHIFT_CERT_DATA": string(config.CertData), + "OPENSHIFT_INSECURE": insecure, + } + + objects := []runtime.Object{ + &dapi.DeploymentConfig{ + ObjectMeta: kapi.ObjectMeta{ + Name: name, + Labels: label, + }, + Triggers: []dapi.DeploymentTriggerPolicy{ + {Type: dapi.DeploymentTriggerOnConfigChange}, + }, + Template: dapi.DeploymentTemplate{ + Strategy: dapi.DeploymentStrategy{ + Type: dapi.DeploymentStrategyTypeRecreate, + }, + ControllerTemplate: kapi.ReplicationControllerSpec{ + Replicas: cfg.Replicas, + Selector: label, + Template: &kapi.PodTemplateSpec{ + ObjectMeta: kapi.ObjectMeta{Labels: label}, + Spec: kapi.PodSpec{ + Containers: []kapi.Container{ + { + Name: "router", + Image: image, + Ports: ports, + Env: env.List(), + }, + }, + }, + }, + }, + }, + }, + } + objects = app.AddServices(objects) + // TODO: label all created objects with the same label - router= + list := &kapi.List{Items: objects} + + if output { + if err := p.PrintObj(list, out); err != nil { + glog.Fatalf("Unable to print object: %v", err) + } + return + } + + bulk := configcmd.Bulk{ + Factory: f.Factory, + Command: cmd, + After: configcmd.NewPrintNameOrErrorAfter(out, os.Stderr), + } + if errs := bulk.Create(list, namespace); len(errs) != 0 { + os.Exit(1) + } + return + } + + fmt.Fprintf(out, "Router %q service exists", name) + }, + } + + cmd.Flags().StringVar(&cfg.Type, "type", "haproxy-router", "The type of router to use - if you specify --images this flag may be ignored.") + cmd.Flags().StringVar(&cfg.ImageTemplate.Format, "images", cfg.ImageTemplate.Format, "The image to base this router on - ${component} will be replaced with --type") + cmd.Flags().BoolVar(&cfg.ImageTemplate.Latest, "latest-images", cfg.ImageTemplate.Latest, "If true, attempt to use the latest images for the router instead of the latest release.") + cmd.Flags().StringVar(&cfg.Ports, "ports", cfg.Ports, "A comma delimited list of ports or port pairs to expose on the router pod. The default is set for HAProxy.") + cmd.Flags().IntVar(&cfg.Replicas, "replicas", cfg.Replicas, "The replication factor of the router; commonly 2 when high availability is desired.") + cmd.Flags().StringVar(&cfg.Labels, "labels", cfg.Labels, "A set of labels to uniquely identify the router and its components.") + cmd.Flags().BoolVar(&cfg.Create, "create", cfg.Create, "Create the router if it does not exist.") + cmd.Flags().StringVar(&cfg.Credentials, "credentials", "", "Path to a .kubeconfig file that will contain the credentials the router should use to contact the master.") + + cmdutil.AddPrinterFlags(cmd) + + return cmd +} + +/* +// Example with generation - this does not have port metadata so its slightly less +// clear to end users. + +registry, imageNamespace, imageName, tag, err := imageapi.SplitDockerPullSpec(image) +if err != nil { + glog.Fatalf("The image value %q is not valid: %v", image, err) +} + +image := &app.ImageRef{ + Namespace: imageNamespace, + Name: imageName, + Registry: registry, + Tag: tag, +} +pipeline, err := app.NewImagePipeline(name, image) +if err != nil { + glog.Fatalf("Unable to set up an image for the router: %v", err) +} +if err := pipeline.NeedsDeployment(nil); err != nil { + glog.Fatalf("Unable to set up a deployment for the router: %v", err) +} +objects, err := pipeline.Objects(app.NewAcceptFirst()) +if err != nil { + glog.Fatalf("Unable to configure objects for deployment: %v", err) +} +objects = app.AddServices(objects) +*/ diff --git a/pkg/cmd/openshift/openshift.go b/pkg/cmd/openshift/openshift.go index e850b939a648..c1f50545cb01 100644 --- a/pkg/cmd/openshift/openshift.go +++ b/pkg/cmd/openshift/openshift.go @@ -13,6 +13,7 @@ import ( "github.com/openshift/origin/pkg/cmd/experimental/login" "github.com/openshift/origin/pkg/cmd/experimental/policy" "github.com/openshift/origin/pkg/cmd/experimental/project" + exrouter "github.com/openshift/origin/pkg/cmd/experimental/router" "github.com/openshift/origin/pkg/cmd/experimental/tokens" "github.com/openshift/origin/pkg/cmd/flagtypes" "github.com/openshift/origin/pkg/cmd/infra/builder" @@ -121,7 +122,7 @@ func newExperimentalCommand(parentName, name string) *cobra.Command { experimental.AddCommand(policy.NewCommandPolicy(f, subName, "policy")) experimental.AddCommand(generate.NewCmdGenerate(f, subName, "generate")) experimental.AddCommand(login.NewCmdLogin(f, subName, "login")) - //experimental.AddCommand(exrouter.NewCmdRouter(f, subName, "router", os.Stdout)) + experimental.AddCommand(exrouter.NewCmdRouter(f, subName, "router", os.Stdout)) return experimental }