func applyAnsibleRC(c *cli.Context) { args := c.Args() if len(args) < 1 { log.Die("Expected an argument!") } hosts := args[0] f := cmdutil.NewFactory(nil) if f == nil { log.Die("Failed to create Kuberentes client factory!") } kubeclient, _ := f.Client() if kubeclient == nil { log.Die("Failed to create Kuberentes client!") } ns, _, _ := f.DefaultNamespace() if len(ns) == 0 { ns = "default" } rcName, err := osExpandAndVerify(c, "rc") if err != nil { fail(err) } inventory, err := osExpandAndVerify(c, "inventory") if err != nil { fail(err) } _, err = ansible.UpdateAnsibleRC(inventory, hosts, kubeclient, ns, rcName) if err != nil { fail(err) } }
func main() { app := cli.NewApp() app.Name = "gosupervise" app.Usage = `Go Supervise This command supervises a remote process inside a Pod inside Kubernetes to make it look and feel like legacy processes running outside of Kubernetes are really running inside Docker inside Kubernetes. ` app.Version = version app.EnableBashCompletion = true app.After = func(c *cli.Context) error { if log.ErrorState { return errors.New("Exiting with errors") } return nil } app.Flags = []cli.Flag{ cli.StringFlag{ Name: "port", Value: "22", Usage: "The port for the remote SSH connection", }, cli.BoolFlag{ Name: "debug", Usage: "Enable verbose debugging output", }, } app.CommandNotFound = func(c *cli.Context, command string) { log.Err("No matching command '%s'", command) cli.ShowAppHelp(c) log.Die("") } app.Commands = []cli.Command{ { Name: "pod", Usage: "Runs the supervisor pod for a single host in a set of hosts from an Ansible inventory.", Description: `This commmand will begin running the supervisor command on one host from the Ansible inventory.`, ArgsUsage: "[hosts] [command]", Action: runAnsiblePod, Flags: []cli.Flag{ cli.StringFlag{ Name: "inventory", Value: "inventory", Usage: "The location of your Ansible inventory file", }, cli.StringFlag{ Name: "rc", Value: "rc.yml", Usage: "The YAML file of the ReplicationController for the supervisors", }, cli.StringFlag{ Name: "password", Value: "$GOSUPERVISE_PASSWORD", Usage: "The password used for WinRM connections", }, cli.BoolFlag{ Name: "winrm", EnvVar: "GOSUPERVISE_WINRM", Usage: "Enables the use of WinRM instead of SSH", }, }, }, { Name: "rc", Usage: "Applies ReplicationController for the supervisors for some hosts in an Ansible inventory.", Description: `This commmand will analyse the hosts in an Ansible inventory and creates or updates the ReplicationController for its supervisors.`, ArgsUsage: "[hosts] [command]", Action: applyAnsibleRC, Flags: []cli.Flag{ cli.StringFlag{ Name: "inventory", Value: "inventory", Usage: "The location of your Ansible inventory file", }, cli.StringFlag{ Name: "rc", Value: "rc.yml", Usage: "The YAML file of the ReplicationController for the supervisors", }, }, }, { Name: "run", Usage: "Runs a supervisor command on a given host as a user without using Ansible.", Description: `This commmand will begin running the supervisor on an avaiable host.`, ArgsUsage: "[string]", Action: run, Flags: []cli.Flag{ cli.StringFlag{ Name: "user", Value: "$GOSUPERVISE_USER", Usage: "The user to use on the remote connection", }, cli.StringFlag{ Name: "privatekey", Value: "$GOSUPERVISE_PRIVATEKEY", Usage: "The private key used for SSH", }, cli.StringFlag{ Name: "host", Value: "$GOSUPERVISE_HOST", Usage: "The host for the remote connection", }, cli.StringFlag{ Name: "command", Value: "$GOSUPERVISE_COMMAND", Usage: "The remote command to invoke on the host", }, cli.StringFlag{ Name: "password", Usage: "The password if using WinRM to execute the command", }, cli.BoolFlag{ Name: "winrm", Usage: "Enables the use of WinRM instead of SSH", }, }, }, } app.Before = func(c *cli.Context) error { log.IsDebugging = c.Bool("debug") return nil } app.RunAndExitOnError() }
func runAnsiblePod(c *cli.Context) { args := c.Args() if len(args) < 2 { log.Die("Expected at least 2 arguments!") } hosts := args[0] command := strings.Join(args[1:], " ") log.Info("running command on a host from %s and command `%s`", hosts, command) f := cmdutil.NewFactory(nil) if f == nil { log.Die("Failed to create Kuberentes client factory!") } kubeclient, _ := f.Client() if kubeclient == nil { log.Die("Failed to create Kuberentes client!") } ns, _, _ := f.DefaultNamespace() if len(ns) == 0 { ns = "default" } rcFile, err := osExpandAndVerify(c, "rc") if err != nil { fail(err) } port, err := osExpandAndVerifyGlobal(c, "port") if err != nil { fail(err) } inventory, err := osExpandAndVerify(c, "inventory") if err != nil { fail(err) } rc, err := k8s.ReadReplicationControllerFromFile(rcFile) if err != nil { fail(err) } rcName := rc.ObjectMeta.Name if len(rcName) == 0 { log.Die("No ReplicationController name in the yaml file %s", rcFile) } hostEntry, err := ansible.ChooseHostAndPrivateKey(inventory, hosts, kubeclient, ns, rcName) if err != nil { fail(err) } host := hostEntry.Host user := hostEntry.User useWinRM := c.Bool("winrm") || hostEntry.UseWinRM if useWinRM { log.Info("Using WinRM to connect to the hosts %s", hosts) password, err := osExpandAndVerify(c, "password") if err != nil { fail(err) } err = winrm.RemoteWinRmCommand(user, password, host, port, command) } else { privatekey := hostEntry.PrivateKey hostPort := host + ":" + port err = ssh.RemoteSshCommand(user, privatekey, hostPort, command) } if err != nil { log.Err("Failed: %v", err) } }
func fail(err error) { log.Die("Failed: %s", err) }