Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hyperkube cleanup #4240

Merged
merged 11 commits into from
Feb 20, 2015
190 changes: 172 additions & 18 deletions cmd/hyperkube/hyperkube.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +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/controllermanager"
"github.com/GoogleCloudPlatform/kubernetes/pkg/hyperkube"
kubelet "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/server"
apiserver "github.com/GoogleCloudPlatform/kubernetes/pkg/master/server"
proxy "github.com/GoogleCloudPlatform/kubernetes/pkg/proxy/server"
sched "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler/server"
"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
}
}

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)
}

hk.AddServer(apiserver.NewHyperkubeServer())
hk.AddServer(controllermanager.NewHyperkubeServer())
hk.AddServer(sched.NewHyperkubeServer())
hk.AddServer(kubelet.NewHyperkubeServer())
hk.AddServer(proxy.NewHyperkubeServer())
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}} <server> [flags]

hk.RunToExit(os.Args)
Servers
{{range .Servers}}
{{.Name}}
{{.Long | trim | wrap " "}}{{end}}
Call '{{.Name}} <server> --help' for help on a specific server.
`
util.ExecuteTemplate(hk.Out(), tt, hk)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package hyperkube
package main

import (
"bytes"
Expand Down
37 changes: 37 additions & 0 deletions cmd/hyperkube/kube-apiserver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2015 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 main

import (
kubeapiserver "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-apiserver/app"
)

// NewKubeAPIServer creates a new hyperkube Server object that includes the
// description and flags.
func NewKubeAPIServer() *Server {
s := kubeapiserver.NewAPIServer()

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(_ *Server, args []string) error {
return s.Run(args)
},
}
s.AddFlags(hks.Flags())
return &hks
}
37 changes: 37 additions & 0 deletions cmd/hyperkube/kube-controller-manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2015 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 main

import (
controllermgr "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-controller-manager/app"
)

// NewKubeControllerManager creates a new hyperkube Server object that includes the
// description and flags.
func NewKubeControllerManager() *Server {
s := controllermgr.NewCMServer()

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(_ *Server, args []string) error {
return s.Run(args)
},
}
s.AddFlags(hks.Flags())
return &hks
}
40 changes: 40 additions & 0 deletions cmd/hyperkube/kube-proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2015 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 main

import (
kubeproxy "github.com/GoogleCloudPlatform/kubernetes/cmd/kube-proxy/app"
)

// NewKubeProxy creates a new hyperkube Server object that includes the
// description and flags.
func NewKubeProxy() *Server {
s := kubeproxy.NewProxyServer()

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(_ *Server, args []string) error {
return s.Run(args)
},
}
s.AddFlags(hks.Flags())
return &hks
}
37 changes: 37 additions & 0 deletions cmd/hyperkube/kube-scheduler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2015 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 main

import (
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() *Server {
s := scheduler.NewSchedulerServer()

hks := Server{
SimpleUsage: "scheduler",
Long: "Implements a Kubernetes scheduler. This will assign pods to kubelets based on capacity and constraints.",
Run: func(_ *Server, args []string) error {
return s.Run(args)
},
}
s.AddFlags(hks.Flags())
return &hks
}