package start
import (
"fmt"
"io"
"net"
"os"
"github.com/golang/glog"
"github.com/spf13/cobra"
kerrors "k8s.io/kubernetes/pkg/api/errors"
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"github.com/openshift/origin/pkg/cmd/flagtypes"
configapi "github.com/openshift/origin/pkg/cmd/server/api"
"github.com/openshift/origin/pkg/cmd/templates"
)
var apiLong = templates.LongDesc(`
Start the master API
This command starts the master API. Running
%[1]s start master %[2]s
will start the server listening for incoming API requests. The server
will run in the foreground until you terminate the process.`)
// NewCommandStartMasterAPI starts only the APIserver
func NewCommandStartMasterAPI(name, basename string, out, errout io.Writer) (*cobra.Command, *MasterOptions) {
options := &MasterOptions{Output: out}
options.DefaultsFromName(basename)
cmd := &cobra.Command{
Use: name,
Short: "Launch master API",
Long: fmt.Sprintf(apiLong, basename, name),
Run: func(c *cobra.Command, args []string) {
if err := options.Complete(); err != nil {
fmt.Fprintln(errout, kcmdutil.UsageError(c, err.Error()))
return
}
if len(options.ConfigFile) == 0 {
fmt.Fprintln(errout, kcmdutil.UsageError(c, "--config is required for this command"))
return
}
if err := options.Validate(args); err != nil {
fmt.Fprintln(errout, kcmdutil.UsageError(c, err.Error()))
return
}
startProfiler()
if err := options.StartMaster(); err != nil {
if kerrors.IsInvalid(err) {
if details := err.(*kerrors.StatusError).ErrStatus.Details; details != nil {
fmt.Fprintf(errout, "Invalid %s %s\n", details.Kind, details.Name)
for _, cause := range details.Causes {
fmt.Fprintf(errout, " %s: %s\n", cause.Field, cause.Message)
}
os.Exit(255)
}
}
glog.Fatal(err)
}
},
}
// allow the master IP address to be overridden on a per process basis
masterAddr := flagtypes.Addr{
Value: "127.0.0.1:8443",
DefaultScheme: "https",
DefaultPort: 8443,
AllowPrefix: true,
}.Default()
// allow the listen address to be overridden on a per process basis
listenArg := &ListenArg{
ListenAddr: flagtypes.Addr{
Value: "127.0.0.1:8444",
DefaultScheme: "https",
DefaultPort: 8444,
AllowPrefix: true,
}.Default(),
}
options.MasterArgs = NewDefaultMasterArgs()
options.MasterArgs.StartAPI = true
options.MasterArgs.OverrideConfig = func(config *configapi.MasterConfig) error {
// we do not currently enable multi host etcd for the cluster
config.EtcdConfig = nil
if config.KubernetesMasterConfig != nil {
if masterAddr.Provided {
if ip := net.ParseIP(masterAddr.Host); ip != nil {
glog.V(2).Infof("Using a masterIP override %q", ip)
config.KubernetesMasterConfig.MasterIP = ip.String()
}
}
if listenArg.ListenAddr.Provided {
addr := listenArg.ListenAddr.URL.Host
glog.V(2).Infof("Using a listen address override %q", addr)
applyBindAddressOverride(addr, config)
}
}
return nil
}
flags := cmd.Flags()
// This command only supports reading from config and the override master address
flags.StringVar(&options.ConfigFile, "config", "", "Location of the master configuration file to run from. Required")
cmd.MarkFlagFilename("config", "yaml", "yml")
flags.Var(&masterAddr, "master", "The address the master should register for itself. Defaults to the master address from the config.")
BindListenArg(listenArg, flags, "")
return cmd, options
}
// applyBindAddressOverride takes a given address and overrides the relevant sections of a MasterConfig
// TODO: move into helpers
func applyBindAddressOverride(addr string, config *configapi.MasterConfig) {
defaultHost, defaultPort, err := net.SplitHostPort(addr)
if err != nil {
// is just a host
defaultHost = addr
}
config.ServingInfo.BindAddress = overrideAddress(config.ServingInfo.BindAddress, defaultHost, defaultPort)
if config.EtcdConfig != nil {
config.EtcdConfig.ServingInfo.BindAddress = overrideAddress(config.EtcdConfig.ServingInfo.BindAddress, defaultHost, "")
config.EtcdConfig.PeerServingInfo.BindAddress = overrideAddress(config.EtcdConfig.PeerServingInfo.BindAddress, defaultHost, "")
}
if config.DNSConfig != nil {
config.DNSConfig.BindAddress = overrideAddress(config.DNSConfig.BindAddress, defaultHost, "")
}
if config.AssetConfig != nil {
config.AssetConfig.ServingInfo.BindAddress = overrideAddress(config.AssetConfig.ServingInfo.BindAddress, defaultHost, defaultPort)
}
}
// overrideAddress applies an optional host or port override to a incoming addr. If host or port are empty they will
// not override the existing addr values.
func overrideAddress(addr, host, port string) string {
existingHost, existingPort, err := net.SplitHostPort(addr)
if err != nil {
if len(host) > 0 {
return host
}
return addr
}
if len(host) > 0 {
existingHost = host
}
if len(port) > 0 {
existingPort = port
}
if len(existingPort) == 0 {
return existingHost
}
return net.JoinHostPort(existingHost, existingPort)
}