Create new hyperkube package.
This is the start of an uber-binary that can morph into any server. Eventually we'll want this to be able to launch multiple servers from a single command line.
This commit is contained in:
184
pkg/hyperkube/hyperkube.go
Normal file
184
pkg/hyperkube/hyperkube.go
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
|
||||
"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{}) {
|
||||
str := fmt.Sprintln(i...)
|
||||
hk.Print(str)
|
||||
}
|
||||
|
||||
// Printf is a convenience method to Printf to the defined output
|
||||
func (hk *HyperKube) Printf(format string, i ...interface{}) {
|
||||
str := fmt.Sprintf(format, i...)
|
||||
hk.Print(str)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
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.Println("Error", err)
|
||||
hk.Usage()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
s, err := hk.FindServer(serverName)
|
||||
if err != nil {
|
||||
hk.Println("Error:", 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.Println("Error:", err)
|
||||
}
|
||||
s.Usage()
|
||||
return err
|
||||
}
|
||||
|
||||
util.InitLogs()
|
||||
err = s.Run(s, s.Flags().Args())
|
||||
if err != nil {
|
||||
hk.Println("Error:", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 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]
|
||||
|
||||
Servers
|
||||
{{range .Servers}}
|
||||
{{.Name}}
|
||||
{{.Long | trim | wrap " "}}{{end}}
|
||||
Call '{{.Name}} <server> --help' for help on a specific server.
|
||||
`
|
||||
util.ExecuteTemplate(hk.Out(), tt, hk)
|
||||
}
|
Reference in New Issue
Block a user