func cmdScp(c *cli.Context) { args := c.Args() if len(args) != 2 { cli.ShowCommandHelp(c, "scp") log.Fatal("Improper number of arguments.") } // TODO: Check that "-3" flag is available in user's version of scp. // It is on every system I've checked, but the manual mentioned it's "newer" sshArgs := append(baseSSHArgs, "-3") if c.Bool("recursive") { sshArgs = append(sshArgs, "-r") } src := args[0] dest := args[1] store := getStore(c) cmd, err := getScpCmd(src, dest, sshArgs, store) if err != nil { log.Fatal(err) } if err := runCmdWithStdIo(*cmd); err != nil { log.Fatal(err) } }
func cmdSsh(c *cli.Context) { args := c.Args() name := args.First() if name == "" { log.Fatal("Error: Please specify a machine name.") } store := getStore(c) host, err := store.Load(name) if err != nil { log.Fatal(err) } currentState, err := host.Driver.GetState() if err != nil { log.Fatal(err) } if currentState != state.Running { log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name) } client, err := host.CreateSSHClient() if err != nil { log.Fatal(err) } if err := client.Shell(c.Args().Tail()...); err != nil { log.Fatal(err) } }
func cmdInspect(c *cli.Context) { tmplString := c.String("format") if tmplString != "" { var tmpl *template.Template var err error if tmpl, err = template.New("").Funcs(funcMap).Parse(tmplString); err != nil { log.Fatalf("Template parsing error: %v\n", err) } jsonHost, err := json.Marshal(getFirstArgHost(c)) if err != nil { log.Fatal(err) } obj := make(map[string]interface{}) if err := json.Unmarshal(jsonHost, &obj); err != nil { log.Fatal(err) } if err := tmpl.Execute(os.Stdout, obj); err != nil { log.Fatal(err) } os.Stdout.Write([]byte{'\n'}) } else { prettyJSON, err := json.MarshalIndent(getFirstArgHost(c), "", " ") if err != nil { log.Fatal(err) } fmt.Println(string(prettyJSON)) } }
func cmdUrl(c *cli.Context) { if len(c.Args()) != 1 { log.Fatal(ErrExpectedOneMachine) } url, err := getFirstArgHost(c).GetURL() if err != nil { log.Fatal(err) } fmt.Println(url) }
func fatalOnError(command func(context *cli.Context) error) func(context *cli.Context) { return func(context *cli.Context) { if err := command(context); err != nil { log.Fatal(err) } } }
func fatalOnError(command func(commandLine CommandLine) error) func(context *cli.Context) { return func(context *cli.Context) { if err := command(&contextCommandLine{context}); err != nil { log.Fatal(err) } } }
func fatalOnError(command func(commandLine CommandLine, api libmachine.API) error) func(context *cli.Context) { return func(context *cli.Context) { api := libmachine.NewClient(mcndirs.GetBaseDir()) if context.GlobalBool("native-ssh") { api.SSHClientType = ssh.Native } api.GithubAPIToken = context.GlobalString("github-api-token") api.Filestore.Path = context.GlobalString("storage-path") crashreport.Configure(context.GlobalString("bugsnag-api-token")) // TODO (nathanleclaire): These should ultimately be accessed // through the libmachine client by the rest of the code and // not through their respective modules. For now, however, // they are also being set the way that they originally were // set to preserve backwards compatibility. mcndirs.BaseDir = api.Filestore.Path mcnutils.GithubAPIToken = api.GithubAPIToken ssh.SetDefaultClient(api.SSHClientType) defer rpcdriver.CloseDrivers() if err := command(&contextCommandLine{context}, api); err != nil { log.Fatal(err) } } }
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) { mcnName := "" p := localbinary.NewLocalBinaryPlugin(driverName) go func() { if err := p.Serve(); err != nil { // If we can't safely load the server, best to just // bail. log.Fatal(err) } }() addr, err := p.Address() if err != nil { return nil, fmt.Errorf("Error attempting to get plugin server address for RPC: %s", err) } rpcclient, err := rpc.DialHTTP("tcp", addr) if err != nil { return nil, err } c := &RpcClientDriver{ Client: NewInternalClient(rpcclient), heartbeatDoneCh: make(chan bool), } go func(heartbeatDoneCh <-chan bool) { for { select { case <-heartbeatDoneCh: return default: if err := c.Client.Call("RpcServerDriver.Heartbeat", struct{}{}, nil); err != nil { log.Warnf("Error attempting heartbeat call to plugin server: %s", err) } time.Sleep(heartbeatInterval) } } }(c.heartbeatDoneCh) var version int if err := c.Client.Call("RpcServerDriver.GetVersion", struct{}{}, &version); err != nil { return nil, err } log.Debug("Using API Version ", version) if err := c.SetConfigRaw(rawDriverData); err != nil { return nil, err } mcnName = c.GetMachineName() p.MachineName = mcnName c.Client.MachineName = mcnName c.plugin = p return c, nil }
func cmdUrl(c *cli.Context) { url, err := getFirstArgHost(c).GetURL() if err != nil { log.Fatal(err) } fmt.Println(url) }
func DumpVal(vals ...interface{}) { for _, val := range vals { prettyJSON, err := json.MarshalIndent(val, "", " ") if err != nil { log.Fatal(err) } log.Debug(string(prettyJSON)) } }
func runCmdWithStdIo(cmd exec.Cmd) error { cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatal(err) } return nil }
func cmdRegenerateCerts(c *cli.Context) { force := c.Bool("force") if force || confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.") { log.Infof("Regenerating TLS certificates") if err := runActionWithContext("configureAuth", c); err != nil { log.Fatal(err) } } }
func main() { libmachine.SetDebug(true) log.SetOutWriter(os.Stdout) log.SetErrWriter(os.Stderr) // returns the familiar store at $HOME/.docker/machine store := libmachine.GetDefaultStore() // over-ride this for now (don't want to muck with my default store) store.Path = "/tmp/automatic" hostName := "myfunhost" // Set some options on the provider... driver := virtualbox.NewDriver(hostName, "/tmp/automatic") driver.CPU = 2 driver.Memory = 2048 h, err := store.NewHost(driver) if err != nil { log.Fatal(err) } h.HostOptions.EngineOptions.StorageDriver = "overlay" if err := libmachine.Create(store, h); err != nil { log.Fatal(err) } out, err := h.RunSSHCommand("df -h") if err != nil { log.Fatal(err) } fmt.Printf("Results of your disk space query:\n%s\n", out) fmt.Println("Powering down machine now...") if err := h.Stop(); err != nil { log.Fatal(err) } }
func cmdStatus(c *cli.Context) { if len(c.Args()) != 1 { log.Fatal(ErrExpectedOneMachine) } host := getFirstArgHost(c) currentState, err := host.Driver.GetState() if err != nil { log.Errorf("error getting state for host %s: %s", host.Name, err) } log.Info(currentState) }
func main() { log.SetDebug(true) client := libmachine.NewClient("/tmp/automatic", "/tmp/automatic/certs") defer client.Close() hostName := "myfunhost" // Set some options on the provider... driver := virtualbox.NewDriver(hostName, "/tmp/automatic") driver.CPU = 2 driver.Memory = 2048 data, err := json.Marshal(driver) if err != nil { log.Fatal(err) } h, err := client.NewHost("virtualbox", data) if err != nil { log.Fatal(err) } h.HostOptions.EngineOptions.StorageDriver = "overlay" if err := client.Create(h); err != nil { log.Fatal(err) } out, err := h.RunSSHCommand("df -h") if err != nil { log.Fatal(err) } fmt.Printf("Results of your disk space query:\n%s\n", out) fmt.Println("Powering down machine now...") if err := h.Stop(); err != nil { log.Fatal(err) } }
func cmdSsh(c *cli.Context) { args := c.Args() name := args.First() if name == "" { log.Fatal("Error: Please specify a machine name.") } store := getStore(c) host, err := store.Load(name) if err != nil { log.Fatal(err) } currentState, err := host.Driver.GetState() if err != nil { log.Fatal(err) } if currentState != state.Running { log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name) } if len(c.Args()) == 1 { err := host.CreateSSHShell() if err != nil { log.Fatal(err) } } else { output, err := host.RunSSHCommand(strings.Join(c.Args().Tail(), " ")) if err != nil { log.Fatal(err) } fmt.Print(output) } }
func matchesName(host *host.Host, names []string) bool { if len(names) == 0 { return true } for _, n := range names { r, err := regexp.Compile(n) if err != nil { log.Fatal(err) } if r.MatchString(host.Driver.GetMachineName()) { return true } } return false }
func cmdRm(c *cli.Context) { if len(c.Args()) == 0 { cli.ShowCommandHelp(c, "rm") log.Fatal("You must specify a machine name") } force := c.Bool("force") isError := false store := getStore(c) for _, hostName := range c.Args() { if err := store.Remove(hostName, force); err != nil { log.Errorf("Error removing machine %s: %s", hostName, err) isError = true } else { log.Infof("Successfully removed %s", hostName) } } if isError { log.Fatal("There was an error removing a machine. To force remove it, pass the -f option. Warning: this might leave it running on the provider.") } }
func cmdActive(c *cli.Context) { if len(c.Args()) > 0 { log.Fatal("Error: Too many arguments given.") } store := getStore(c) host, err := getActiveHost(store) if err != nil { log.Fatalf("Error getting active host: %s", err) } if host != nil { fmt.Println(host.Name) } }
func hypercoreExec(args ...string) (string, error) { var Password string cmd := exec.Command("sudo", HypercoreCmd, strings.Join(args, " ")) cmd.Stdin = strings.NewReader(Password) var stdout bytes.Buffer cmd.Stdout = &stdout log.Debugf("executing: %v %v %v", cmd, args, stdout.String()) err := cmd.Run() if err != nil { log.Fatal(err) } log.Debug(stdout.String()) return stdout.String(), err }
func confirmInput(msg string) bool { fmt.Printf("%s (y/n): ", msg) var resp string _, err := fmt.Scanln(&resp) if err != nil { log.Fatal(err) } if strings.Index(strings.ToLower(resp), "y") == 0 { return true } return false }
func cmdConfig(c *cli.Context) { if len(c.Args()) != 1 { log.Fatal(ErrExpectedOneMachine) } h := getFirstArgHost(c) dockerHost, authOptions, err := runConnectionBoilerplate(h, c) if err != nil { log.Fatalf("Error running connection boilerplate: %s", err) } log.Debug(dockerHost) fmt.Printf("--tlsverify --tlscacert=%q --tlscert=%q --tlskey=%q -H=%s", authOptions.CaCertPath, authOptions.ClientCertPath, authOptions.ClientKeyPath, dockerHost) }
func runActionWithContext(actionName string, c *cli.Context) error { store := getStore(c) hosts, err := getHostsFromContext(c) if err != nil { return err } if len(hosts) == 0 { log.Fatal(ErrNoMachineSpecified) } runActionForeachMachine(actionName, hosts) for _, h := range hosts { if err := store.Save(h); err != nil { return fmt.Errorf("Error saving host to store: %s", err) } } return nil }
func (h *Host) Upgrade() error { machineState, err := h.Driver.GetState() if err != nil { return err } if machineState != state.Running { log.Fatal(errMachineMustBeRunningForUpgrade) } provisioner, err := provision.DetectProvisioner(h.Driver) if err != nil { return err } if err := provisioner.Package("docker", pkgaction.Upgrade); err != nil { return err } if err := provisioner.Service("docker", serviceaction.Restart); err != nil { return err } return nil }
func cmdEnv(c *cli.Context) { if len(c.Args()) != 1 && !c.Bool("unset") { log.Fatal(improperEnvArgsError) } h := getFirstArgHost(c) dockerHost, authOptions, err := runConnectionBoilerplate(h, c) if err != nil { log.Fatalf("Error running connection boilerplate: %s", err) } userShell := c.String("shell") if userShell == "" { shell, err := detectShell() if err != nil { log.Fatal(err) } userShell = shell } t := template.New("envConfig") usageHint := generateUsageHint(c.App.Name, c.Args().First(), userShell) shellCfg := &ShellConfig{ DockerCertPath: authOptions.CertDir, DockerHost: dockerHost, DockerTLSVerify: "1", UsageHint: usageHint, MachineName: h.Name, } if c.Bool("no-proxy") { ip, err := h.Driver.GetIP() if err != nil { log.Fatalf("Error getting host IP: %s", err) } // first check for an existing lower case no_proxy var noProxyVar := "no_proxy" noProxyValue := os.Getenv("no_proxy") // otherwise default to allcaps HTTP_PROXY if noProxyValue == "" { noProxyVar = "NO_PROXY" noProxyValue = os.Getenv("NO_PROXY") } // add the docker host to the no_proxy list idempotently switch { case noProxyValue == "": noProxyValue = ip case strings.Contains(noProxyValue, ip): //ip already in no_proxy list, nothing to do default: noProxyValue = fmt.Sprintf("%s,%s", noProxyValue, ip) } shellCfg.NoProxyVar = noProxyVar shellCfg.NoProxyValue = noProxyValue } // unset vars if c.Bool("unset") { switch userShell { case "fish": shellCfg.Prefix = "set -e " shellCfg.Delimiter = "" shellCfg.Suffix = ";\n" case "powershell": shellCfg.Prefix = "Remove-Item Env:\\\\" shellCfg.Delimiter = "" shellCfg.Suffix = "\n" case "cmd": // since there is no way to unset vars in cmd just reset to empty shellCfg.DockerCertPath = "" shellCfg.DockerHost = "" shellCfg.DockerTLSVerify = "" shellCfg.Prefix = "set " shellCfg.Delimiter = "=" shellCfg.Suffix = "\n" default: shellCfg.Prefix = "unset " shellCfg.Delimiter = " " shellCfg.Suffix = "\n" } tmpl, err := t.Parse(envTmpl) if err != nil { log.Fatal(err) } if err := tmpl.Execute(os.Stdout, shellCfg); err != nil { log.Fatal(err) } return } switch userShell { case "fish": shellCfg.Prefix = "set -x " shellCfg.Suffix = "\";\n" shellCfg.Delimiter = " \"" case "powershell": shellCfg.Prefix = "$Env:" shellCfg.Suffix = "\"\n" shellCfg.Delimiter = " = \"" case "cmd": shellCfg.Prefix = "set " shellCfg.Suffix = "\n" shellCfg.Delimiter = "=" default: shellCfg.Prefix = "export " shellCfg.Suffix = "\"\n" shellCfg.Delimiter = "=\"" } tmpl, err := t.Parse(envTmpl) if err != nil { log.Fatal(err) } if err := tmpl.Execute(os.Stdout, shellCfg); err != nil { log.Fatal(err) } }
func fatal(args ...interface{}) { close(RpcClientDriversCh) <-RpcDriversClosedCh log.Fatal(args...) }
func cmdUpgrade(c *cli.Context) { if err := runActionWithContext("upgrade", c); err != nil { log.Fatal(err) } }
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) { mcnName := "" p := localbinary.NewLocalBinaryPlugin(driverName) c := &RpcClientDriver{} go func() { if err := p.Serve(); err != nil { // If we can't safely load the server, best to just // bail. log.Fatal(err) } }() addr, err := p.Address() if err != nil { return nil, fmt.Errorf("Error attempting to get plugin server address for RPC: %s", err) } rpcclient, err := rpc.DialHTTP("tcp", addr) if err != nil { return nil, err } c.Client = NewInternalClient(rpcclient) go func() { for { call := <-c.Client.Calls log.Debugf("(%s) Got msg %+v", mcnName, call) if call.ServiceMethod == "RpcServerDriver.Close" { p.Close() } c.Client.CallErrs <- c.Client.RpcClient.Call(call.ServiceMethod, call.Args, call.Reply) if call.ServiceMethod == "RpcServerDriver.Close" { // If we're messaging the server to close, // we're not accepting any more RPC calls at // all, so return from this function // (subsequent "requests" to make a call by // sending on the Calls channel will simply // block and never go through) return } } }() var version int if err := c.Client.Call("RpcServerDriver.GetVersion", struct{}{}, &version); err != nil { return nil, err } log.Debug("Using API Version ", version) if err := c.SetConfigRaw(rawDriverData); err != nil { return nil, err } mcnName = c.GetMachineName() p.MachineName = mcnName return c, nil }
func fatal(args ...interface{}) { log.Fatal(args...) }
func cmdStart(c *cli.Context) { if err := runActionWithContext("start", c); err != nil { log.Fatal(err) } log.Info("Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.") }