diff --git a/cmd/hyperkube/hyperkube.go b/cmd/hyperkube/hyperkube.go index b8ed0ab46f..d8499e5990 100644 --- a/cmd/hyperkube/hyperkube.go +++ b/cmd/hyperkube/hyperkube.go @@ -14,27 +14,186 @@ See the License for the specific language governing permissions and limitations under the License. */ -// A binary that can morph into all of the other kubernetes binaries. You can -// also soft-link to it busybox style. package main import ( + "errors" + "flag" + "fmt" + "io" + "io/ioutil" "os" + "path" - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" + "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/version/verflag" + + "github.com/spf13/pflag" ) -func main() { - hk := hyperkube.HyperKube{ - Name: "hyperkube", - Long: "This is an all-in-one binary that can run any of the various Kubernetes servers.", +// HyperKube represents a single binary that can morph/manage into multiple +// servers. +type HyperKube struct { + Name string // The executable name, used for help and soft-link invocation + Long string // A long description of the binary. It will be world wrapped before output. + + servers []Server + baseFlags *pflag.FlagSet + out io.Writer + helpFlagVal bool +} + +// AddServer adds a server to the HyperKube object. +func (hk *HyperKube) AddServer(s *Server) { + hk.servers = append(hk.servers, *s) + hk.servers[len(hk.servers)-1].hk = hk +} + +// FindServer will find a specific server named name. +func (hk *HyperKube) FindServer(name string) (*Server, error) { + for _, s := range hk.servers { + if s.Name() == name { + return &s, nil + } + } + return nil, fmt.Errorf("Server not found: %s", name) +} + +// Servers returns a list of all of the registred servers +func (hk *HyperKube) Servers() []Server { + return hk.servers +} + +// Flags returns a flagset for "global" flags. +func (hk *HyperKube) Flags() *pflag.FlagSet { + if hk.baseFlags == nil { + hk.baseFlags = pflag.NewFlagSet(hk.Name, pflag.ContinueOnError) + hk.baseFlags.SetOutput(ioutil.Discard) + hk.baseFlags.BoolVarP(&hk.helpFlagVal, "help", "h", false, "help for "+hk.Name) + + // These will add all of the "global" flags (defined with both the + // flag and pflag packages) to the new flag set we have. + util.AddFlagSetToPFlagSet(flag.CommandLine, hk.baseFlags) + util.AddPFlagSetToPFlagSet(pflag.CommandLine, hk.baseFlags) + + } + return hk.baseFlags +} + +// Out returns the io.Writer that is used for all usage/error information +func (hk *HyperKube) Out() io.Writer { + if hk.out == nil { + hk.out = os.Stderr + } + return hk.out +} + +// SetOut sets the output writer for all usage/error information +func (hk *HyperKube) SetOut(w io.Writer) { + hk.out = w +} + +// Print is a convenience method to Print to the defined output +func (hk *HyperKube) Print(i ...interface{}) { + fmt.Fprint(hk.Out(), i...) +} + +// Println is a convenience method to Println to the defined output +func (hk *HyperKube) Println(i ...interface{}) { + fmt.Fprintln(hk.Out(), i...) +} + +// Printf is a convenience method to Printf to the defined output +func (hk *HyperKube) Printf(format string, i ...interface{}) { + fmt.Fprintf(hk.Out(), format, i...) +} + +// Run the server. This will pick the appropriate server and run it. +func (hk *HyperKube) Run(args []string) error { + // If we are called directly, parse all flags up to the first real + // argument. That should be the server to run. + baseCommand := path.Base(args[0]) + serverName := baseCommand + if serverName == hk.Name { + args = args[1:] + + baseFlags := hk.Flags() + baseFlags.SetInterspersed(false) // Only parse flags up to the next real command + err := baseFlags.Parse(args) + if err != nil || hk.helpFlagVal { + if err != nil { + hk.Println("Error:", err) + } + hk.Usage() + return err + } + + verflag.PrintAndExitIfRequested() + + args = baseFlags.Args() + if len(args) > 0 && len(args[0]) > 0 { + serverName = args[0] + baseCommand = baseCommand + " " + serverName + args = args[1:] + } else { + err = errors.New("No server specified") + hk.Printf("Error: %v\n\n", err) + hk.Usage() + return err + } } - hk.AddServer(NewKubeAPIServer()) - hk.AddServer(NewKubeControllerManager()) - hk.AddServer(NewScheduler()) - hk.AddServer(NewKubelet()) - hk.AddServer(NewKubeProxy()) + s, err := hk.FindServer(serverName) + if err != nil { + hk.Printf("Error: %v\n\n", err) + hk.Usage() + return err + } - hk.RunToExit(os.Args) + util.AddPFlagSetToPFlagSet(hk.Flags(), s.Flags()) + err = s.Flags().Parse(args) + if err != nil || hk.helpFlagVal { + if err != nil { + hk.Printf("Error: %v\n\n", err) + } + s.Usage() + return err + } + + verflag.PrintAndExitIfRequested() + + util.InitLogs() + defer util.FlushLogs() + + err = s.Run(s, s.Flags().Args()) + if err != nil { + hk.Println("Error:", err) + } + + return err +} + +// RunToExit will run the hyperkube and then call os.Exit with an appropriate exit code. +func (hk *HyperKube) RunToExit(args []string) { + err := hk.Run(args) + if err != nil { + os.Exit(1) + } + os.Exit(0) +} + +// Usage will write out a summary for all servers that this binary supports. +func (hk *HyperKube) Usage() { + tt := `{{if .Long}}{{.Long | trim | wrap ""}} +{{end}}Usage + + {{.Name}} [flags] + +Servers +{{range .Servers}} + {{.Name}} +{{.Long | trim | wrap " "}}{{end}} +Call '{{.Name}} --help' for help on a specific server. +` + util.ExecuteTemplate(hk.Out(), tt, hk) } diff --git a/pkg/hyperkube/hyperkube_test.go b/cmd/hyperkube/hyperkube_test.go similarity index 99% rename from pkg/hyperkube/hyperkube_test.go rename to cmd/hyperkube/hyperkube_test.go index c88336c053..ccd83217c9 100644 --- a/pkg/hyperkube/hyperkube_test.go +++ b/cmd/hyperkube/hyperkube_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package hyperkube +package main import ( "bytes" diff --git a/cmd/hyperkube/kube-apiserver.go b/cmd/hyperkube/kube-apiserver.go index 666db8f8ec..0d8ee9ac53 100644 --- a/cmd/hyperkube/kube-apiserver.go +++ b/cmd/hyperkube/kube-apiserver.go @@ -18,18 +18,17 @@ package main import ( kubeapiserver "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-apiserver/app" - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" ) // NewKubeAPIServer creates a new hyperkube Server object that includes the // description and flags. -func NewKubeAPIServer() *hyperkube.Server { +func NewKubeAPIServer() *Server { s := kubeapiserver.NewAPIServer() - hks := hyperkube.Server{ + hks := Server{ SimpleUsage: "apiserver", Long: "The main API entrypoint and interface to the storage system. The API server is also the focal point for all authorization decisions.", - Run: func(_ *hyperkube.Server, args []string) error { + Run: func(_ *Server, args []string) error { return s.Run(args) }, } diff --git a/cmd/hyperkube/kube-controller-manager.go b/cmd/hyperkube/kube-controller-manager.go index c59928687e..b501c3d5de 100644 --- a/cmd/hyperkube/kube-controller-manager.go +++ b/cmd/hyperkube/kube-controller-manager.go @@ -18,18 +18,17 @@ package main import ( controllermgr "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-controller-manager/app" - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" ) // NewKubeControllerManager creates a new hyperkube Server object that includes the // description and flags. -func NewKubeControllerManager() *hyperkube.Server { +func NewKubeControllerManager() *Server { s := controllermgr.NewCMServer() - hks := hyperkube.Server{ + hks := Server{ SimpleUsage: "controller-manager", Long: "A server that runs a set of active components. This includes replication controllers, service endpoints and nodes.", - Run: func(_ *hyperkube.Server, args []string) error { + Run: func(_ *Server, args []string) error { return s.Run(args) }, } diff --git a/cmd/hyperkube/kube-proxy.go b/cmd/hyperkube/kube-proxy.go index 088f25368b..4e3daf609d 100644 --- a/cmd/hyperkube/kube-proxy.go +++ b/cmd/hyperkube/kube-proxy.go @@ -18,21 +18,20 @@ package main import ( kubeproxy "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-proxy/app" - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" ) // NewKubeProxy creates a new hyperkube Server object that includes the // description and flags. -func NewKubeProxy() *hyperkube.Server { +func NewKubeProxy() *Server { s := kubeproxy.NewProxyServer() - hks := hyperkube.Server{ + hks := Server{ SimpleUsage: "proxy", Long: `The Kubernetes proxy server is responsible for taking traffic directed at services and forwarding it to the appropriate pods. It generally runs on nodes next to the Kubelet and proxies traffic from local pods to remote pods. It is also used when handling incoming external traffic.`, - Run: func(_ *hyperkube.Server, args []string) error { + Run: func(_ *Server, args []string) error { return s.Run(args) }, } diff --git a/cmd/hyperkube/kube-scheduler.go b/cmd/hyperkube/kube-scheduler.go index 3bf4f49180..cff643fc65 100644 --- a/cmd/hyperkube/kube-scheduler.go +++ b/cmd/hyperkube/kube-scheduler.go @@ -17,19 +17,18 @@ limitations under the License. package main import ( - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" scheduler "github.com/GoogleCloudPlatform/kubernetes/plugin/cmd/kube-scheduler/app" ) // NewScheduler creates a new hyperkube Server object that includes the // description and flags. -func NewScheduler() *hyperkube.Server { +func NewScheduler() *Server { s := scheduler.NewSchedulerServer() - hks := hyperkube.Server{ + hks := Server{ SimpleUsage: "scheduler", Long: "Implements a Kubernetes scheduler. This will assign pods to kubelets based on capacity and constraints.", - Run: func(_ *hyperkube.Server, args []string) error { + Run: func(_ *Server, args []string) error { return s.Run(args) }, } diff --git a/cmd/hyperkube/kubelet.go b/cmd/hyperkube/kubelet.go index 13c2c062a7..b9c404f198 100644 --- a/cmd/hyperkube/kubelet.go +++ b/cmd/hyperkube/kubelet.go @@ -18,14 +18,13 @@ package main import ( kubelet "github.com/GoogleCloudPlatform/kubernetes/cmd/kubelet/app" - "github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube" ) // NewKubelet creates a new hyperkube Server object that includes the // description and flags. -func NewKubelet() *hyperkube.Server { +func NewKubelet() *Server { s := kubelet.NewKubeletServer() - hks := hyperkube.Server{ + hks := Server{ SimpleUsage: "kubelet", Long: `The kubelet binary is responsible for maintaining a set of containers on a particular node. It syncs data from a variety of sources including a @@ -33,7 +32,7 @@ func NewKubelet() *hyperkube.Server { queries Docker to see what is currently running. It synchronizes the configuration data, with the running set of containers by starting or stopping Docker containers.`, - Run: func(_ *hyperkube.Server, args []string) error { + Run: func(_ *Server, args []string) error { return s.Run(args) }, } diff --git a/cmd/hyperkube/main.go b/cmd/hyperkube/main.go new file mode 100644 index 0000000000..3692788989 --- /dev/null +++ b/cmd/hyperkube/main.go @@ -0,0 +1,38 @@ +/* +Copyright 2014 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// A binary that can morph into all of the other kubernetes binaries. You can +// also soft-link to it busybox style. +package main + +import ( + "os" +) + +func main() { + hk := HyperKube{ + Name: "hyperkube", + Long: "This is an all-in-one binary that can run any of the various Kubernetes servers.", + } + + hk.AddServer(NewKubeAPIServer()) + hk.AddServer(NewKubeControllerManager()) + hk.AddServer(NewScheduler()) + hk.AddServer(NewKubelet()) + hk.AddServer(NewKubeProxy()) + + hk.RunToExit(os.Args) +} diff --git a/pkg/hyperkube/server.go b/cmd/hyperkube/server.go similarity index 99% rename from pkg/hyperkube/server.go rename to cmd/hyperkube/server.go index 697211b5f1..4c29f1df32 100644 --- a/pkg/hyperkube/server.go +++ b/cmd/hyperkube/server.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package hyperkube +package main import ( "io/ioutil" diff --git a/pkg/hyperkube/hyperkube.go b/pkg/hyperkube/hyperkube.go deleted file mode 100644 index f38aec289e..0000000000 --- a/pkg/hyperkube/hyperkube.go +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package hyperkube - -import ( - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "runtime" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/GoogleCloudPlatform/kubernetes/pkg/version/verflag" - - "github.com/spf13/pflag" -) - -// HyperKube represents a single binary that can morph/manage into multiple -// servers. -type HyperKube struct { - Name string // The executable name, used for help and soft-link invocation - Long string // A long description of the binary. It will be world wrapped before output. - - servers []Server - baseFlags *pflag.FlagSet - out io.Writer - helpFlagVal bool -} - -// AddServer adds a server to the HyperKube object. -func (hk *HyperKube) AddServer(s *Server) { - hk.servers = append(hk.servers, *s) - hk.servers[len(hk.servers)-1].hk = hk -} - -// FindServer will find a specific server named name. -func (hk *HyperKube) FindServer(name string) (*Server, error) { - for _, s := range hk.servers { - if s.Name() == name { - return &s, nil - } - } - return nil, fmt.Errorf("Server not found: %s", name) -} - -// Servers returns a list of all of the registred servers -func (hk *HyperKube) Servers() []Server { - return hk.servers -} - -// Flags returns a flagset for "global" flags. -func (hk *HyperKube) Flags() *pflag.FlagSet { - if hk.baseFlags == nil { - hk.baseFlags = pflag.NewFlagSet(hk.Name, pflag.ContinueOnError) - hk.baseFlags.SetOutput(ioutil.Discard) - hk.baseFlags.BoolVarP(&hk.helpFlagVal, "help", "h", false, "help for "+hk.Name) - - // These will add all of the "global" flags (defined with both the - // flag and pflag packages) to the new flag set we have. - util.AddFlagSetToPFlagSet(flag.CommandLine, hk.baseFlags) - util.AddPFlagSetToPFlagSet(pflag.CommandLine, hk.baseFlags) - - } - return hk.baseFlags -} - -// Out returns the io.Writer that is used for all usage/error information -func (hk *HyperKube) Out() io.Writer { - if hk.out == nil { - hk.out = os.Stderr - } - return hk.out -} - -// SetOut sets the output writer for all usage/error information -func (hk *HyperKube) SetOut(w io.Writer) { - hk.out = w -} - -// Print is a convenience method to Print to the defined output -func (hk *HyperKube) Print(i ...interface{}) { - fmt.Fprint(hk.Out(), i...) -} - -// Println is a convenience method to Println to the defined output -func (hk *HyperKube) Println(i ...interface{}) { - fmt.Fprintln(hk.Out(), i...) -} - -// Printf is a convenience method to Printf to the defined output -func (hk *HyperKube) Printf(format string, i ...interface{}) { - fmt.Fprintf(hk.Out(), format, i...) -} - -// Run the server. This will pick the appropriate server and run it. -func (hk *HyperKube) Run(args []string) error { - // If we are called directly, parse all flags up to the first real - // argument. That should be the server to run. - baseCommand := path.Base(args[0]) - serverName := baseCommand - if serverName == hk.Name { - args = args[1:] - - baseFlags := hk.Flags() - baseFlags.SetInterspersed(false) // Only parse flags up to the next real command - err := baseFlags.Parse(args) - if err != nil || hk.helpFlagVal { - if err != nil { - hk.Println("Error:", err) - } - hk.Usage() - return err - } - - verflag.PrintAndExitIfRequested() - - args = baseFlags.Args() - if len(args) > 0 && len(args[0]) > 0 { - serverName = args[0] - baseCommand = baseCommand + " " + serverName - args = args[1:] - } else { - err = errors.New("No server specified") - hk.Printf("Error: %v\n\n", err) - hk.Usage() - return err - } - } - - s, err := hk.FindServer(serverName) - if err != nil { - hk.Printf("Error: %v\n\n", err) - hk.Usage() - return err - } - - util.AddPFlagSetToPFlagSet(hk.Flags(), s.Flags()) - err = s.Flags().Parse(args) - if err != nil || hk.helpFlagVal { - if err != nil { - hk.Printf("Error: %v\n\n", err) - } - s.Usage() - return err - } - - verflag.PrintAndExitIfRequested() - - util.InitLogs() - defer util.FlushLogs() - - err = s.Run(s, s.Flags().Args()) - if err != nil { - hk.Println("Error:", err) - } - - return err -} - -// RunToExit will run the hyperkube and then call os.Exit with an appropriate exit code. -func (hk *HyperKube) RunToExit(args []string) { - runtime.GOMAXPROCS(runtime.NumCPU()) - err := hk.Run(args) - if err != nil { - fmt.Fprint(os.Stderr, err.Error()) - os.Exit(1) - } - os.Exit(0) -} - -// Usage will write out a summary for all servers that this binary supports. -func (hk *HyperKube) Usage() { - tt := `{{if .Long}}{{.Long | trim | wrap ""}} -{{end}}Usage - - {{.Name}} [flags] - -Servers -{{range .Servers}} - {{.Name}} -{{.Long | trim | wrap " "}}{{end}} -Call '{{.Name}} --help' for help on a specific server. -` - util.ExecuteTemplate(hk.Out(), tt, hk) -}