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 removeFileIfExists(name string) error { if _, err := os.Stat(name); err == nil { if err := os.Remove(name); err != nil { log.Fatalf("Error removing temporary download file: %s", err) } } return nil }
func cmdNotFound(c *cli.Context, command string) { log.Fatalf( "%s: '%s' is not a %s command. See '%s --help'.", c.App.Name, command, c.App.Name, os.Args[0], ) }
// Download boot2docker ISO image for the given tag and save it at dest. func (b *B2dUtils) DownloadISO(dir, file, isoUrl string) error { u, err := url.Parse(isoUrl) var src io.ReadCloser if u.Scheme == "file" || u.Scheme == "" { s, err := os.Open(u.Path) if err != nil { return err } src = s } else { client := getClient() s, err := client.Get(isoUrl) if err != nil { return err } src = s.Body } defer src.Close() // Download to a temp file first then rename it to avoid partial download. f, err := ioutil.TempFile(dir, file+".tmp") if err != nil { return err } defer func() { if err := removeFileIfExists(f.Name()); err != nil { log.Fatalf("Error removing file: %s", err) } }() if _, err := io.Copy(f, src); err != nil { // TODO: display download progress? return err } if err := f.Close(); err != nil { return err } // Dest is the final path of the boot2docker.iso file. dest := filepath.Join(dir, file) // Windows can't rename in place, so remove the old file before // renaming the temporary downloaded file. if err := removeFileIfExists(dest); err != nil { return err } if err := os.Rename(f.Name(), dest); err != nil { return err } return nil }
func NewDriver() *Driver { d := &Driver{} conn, err := libvirt.NewVirConnection(d.connectionString) if err != nil { log.Fatalf("Failed to connect to libvirt: %s", err) } d.conn = &conn d.PrivateNetwork = privateNetworkName return d }
func generateId() string { rb := make([]byte, 10) _, err := rand.Read(rb) if err != nil { log.Fatalf("Unable to generate id: %s", err) } h := md5.New() io.WriteString(h, string(rb)) return fmt.Sprintf("%x", h.Sum(nil)) }
func getFirstArgHost(c *cli.Context) *host.Host { store := getStore(c) hostName := c.Args().First() h, err := store.Load(hostName) if err != nil { // I guess I feel OK with bailing here since if we can't get // the host reliably we're definitely not going to be able to // do anything else interesting, but also this premature exit // feels wrong to me. Let's revisit it later. log.Fatalf("Error trying to get host %q: %s", hostName, err) } return h }
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 NewDriver(hostName, storePath string) drivers.Driver { conn, err := libvirt.NewVirConnection(connectionString) if err != nil { log.Fatalf("Failed to connect to libvirt: %s", err) return nil } return &Driver{ conn: &conn, PrivateNetwork: privateNetworkName, BaseDriver: &drivers.BaseDriver{ MachineName: hostName, StorePath: storePath, }, } }
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 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 tokenFromWeb(config *oauth.Config) *oauth.Token { randState := fmt.Sprintf("st%d", time.Now().UnixNano()) config.RedirectURL = RedirectURI authURL := config.AuthCodeURL(randState) log.Info("Opening auth URL in browser.") log.Info(authURL) log.Info("If the URL doesn't open please open it manually and copy the code here.") openURL(authURL) code := getCodeFromStdin() log.Infof("Got code: %s", code) t := &oauth.Transport{ Config: config, Transport: http.DefaultTransport, } _, err := t.Exchange(code) if err != nil { log.Fatalf("Token exchange error: %v", err) } return t.Token }
func fatalf(fmtString string, args ...interface{}) { close(RpcClientDriversCh) <-RpcDriversClosedCh log.Fatalf(fmtString, args...) }
func fatalf(fmtString string, args ...interface{}) { log.Fatalf(fmtString, args...) }
func cmdCreate(c *cli.Context) { var ( driver drivers.Driver ) driverName := c.String("driver") name := c.Args().First() certInfo := getCertPathInfoFromContext(c) storePath := c.GlobalString("storage-path") store := &persist.Filestore{ Path: storePath, CaCertPath: certInfo.CaCertPath, CaPrivateKeyPath: certInfo.CaPrivateKeyPath, } // TODO: Not really a fan of "none" as the default driver... if driverName != "none" { var err error c.App.Commands, err = trimDriverFlags(driverName, c.App.Commands) if err != nil { log.Fatal(err) } } if name == "" { cli.ShowCommandHelp(c, "create") log.Fatal("You must specify a machine name") } if len(c.Args()) > 1 { log.Fatalf("Invalid command line. Found extra arguments %v", c.Args()[1:]) } validName := host.ValidateHostName(name) if !validName { log.Fatal("Error creating machine: ", mcnerror.ErrInvalidHostname) } if err := validateSwarmDiscovery(c.String("swarm-discovery")); err != nil { log.Fatalf("Error parsing swarm discovery: %s", err) } hostOptions := &host.HostOptions{ AuthOptions: &auth.AuthOptions{ CertDir: mcndirs.GetMachineCertDir(), CaCertPath: certInfo.CaCertPath, CaPrivateKeyPath: certInfo.CaPrivateKeyPath, ClientCertPath: certInfo.ClientCertPath, ClientKeyPath: certInfo.ClientKeyPath, ServerCertPath: filepath.Join(mcndirs.GetMachineDir(), name, "server.pem"), ServerKeyPath: filepath.Join(mcndirs.GetMachineDir(), name, "server-key.pem"), StorePath: filepath.Join(mcndirs.GetMachineDir(), name), }, EngineOptions: &engine.EngineOptions{ ArbitraryFlags: c.StringSlice("engine-opt"), Env: c.StringSlice("engine-env"), InsecureRegistry: c.StringSlice("engine-insecure-registry"), Labels: c.StringSlice("engine-label"), RegistryMirror: c.StringSlice("engine-registry-mirror"), StorageDriver: c.String("engine-storage-driver"), TlsVerify: true, InstallURL: c.String("engine-install-url"), }, SwarmOptions: &swarm.SwarmOptions{ IsSwarm: c.Bool("swarm"), Image: c.String("swarm-image"), Master: c.Bool("swarm-master"), Discovery: c.String("swarm-discovery"), Address: c.String("swarm-addr"), Host: c.String("swarm-host"), Strategy: c.String("swarm-strategy"), ArbitraryFlags: c.StringSlice("swarm-opt"), }, } driver, err := driverfactory.NewDriver(driverName, name, storePath) if err != nil { log.Fatalf("Error trying to get driver: %s", err) } h, err := store.NewHost(driver) if err != nil { log.Fatalf("Error getting new host: %s", err) } h.HostOptions = hostOptions exists, err := store.Exists(h.Name) if err != nil { log.Fatalf("Error checking if host exists: %s", err) } if exists { log.Fatal(mcnerror.ErrHostAlreadyExists{ Name: h.Name, }) } // TODO: This should be moved out of the driver and done in the // commands module. if err := h.Driver.SetConfigFromFlags(c); err != nil { log.Fatalf("Error setting machine configuration from flags provided: %s", err) } if err := libmachine.Create(store, h); err != nil { log.Fatalf("Error creating machine: %s", err) } info := fmt.Sprintf("%s env %s", os.Args[0], name) log.Infof("To see how to connect Docker to this machine, run: %s", info) }
func ConfigureAuth(p Provisioner) error { var ( err error ) driver := p.GetDriver() machineName := driver.GetMachineName() authOptions := p.GetAuthOptions() org := machineName bits := 2048 ip, err := driver.GetIP() if err != nil { return err } log.Info("Copying certs to the local machine directory...") if err := mcnutils.CopyFile(authOptions.CaCertPath, filepath.Join(authOptions.StorePath, "ca.pem")); err != nil { log.Fatalf("Error copying ca.pem to machine dir: %s", err) } if err := mcnutils.CopyFile(authOptions.ClientCertPath, filepath.Join(authOptions.StorePath, "cert.pem")); err != nil { log.Fatalf("Error copying cert.pem to machine dir: %s", err) } if err := mcnutils.CopyFile(authOptions.ClientKeyPath, filepath.Join(authOptions.StorePath, "key.pem")); err != nil { log.Fatalf("Error copying key.pem to machine dir: %s", err) } log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s", authOptions.ServerCertPath, authOptions.CaCertPath, authOptions.CaPrivateKeyPath, org, ) // TODO: Switch to passing just authOptions to this func // instead of all these individual fields err = cert.GenerateCert( []string{ip}, authOptions.ServerCertPath, authOptions.ServerKeyPath, authOptions.CaCertPath, authOptions.CaPrivateKeyPath, org, bits, ) if err != nil { return fmt.Errorf("error generating server cert: %s", err) } if err := p.Service("docker", serviceaction.Stop); err != nil { return err } // upload certs and configure TLS auth caCert, err := ioutil.ReadFile(authOptions.CaCertPath) if err != nil { return err } serverCert, err := ioutil.ReadFile(authOptions.ServerCertPath) if err != nil { return err } serverKey, err := ioutil.ReadFile(authOptions.ServerKeyPath) if err != nil { return err } log.Info("Copying certs to the remote machine...") // printf will choke if we don't pass a format string because of the // dashes, so that's the reason for the '%%s' certTransferCmdFmt := "printf '%%s' '%s' | sudo tee %s" // These ones are for Jessie and Mike <3 <3 <3 if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(caCert), authOptions.CaCertRemotePath)); err != nil { return err } if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(serverCert), authOptions.ServerCertRemotePath)); err != nil { return err } if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(serverKey), authOptions.ServerKeyRemotePath)); err != nil { return err } dockerUrl, err := driver.GetURL() if err != nil { return err } u, err := url.Parse(dockerUrl) if err != nil { return err } dockerPort := 2376 parts := strings.Split(u.Host, ":") if len(parts) == 2 { dPort, err := strconv.Atoi(parts[1]) if err != nil { return err } dockerPort = dPort } dkrcfg, err := p.GenerateDockerOptions(dockerPort) if err != nil { return err } log.Info("Setting Docker configuration on the remote daemon...") if _, err = p.SSHCommand(fmt.Sprintf("printf %%s \"%s\" | sudo tee %s", dkrcfg.EngineOptions, dkrcfg.EngineOptionsPath)); err != nil { return err } if err := p.Service("docker", serviceaction.Start); err != nil { return err } if err := waitForDocker(p, dockerPort); 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 BootstrapCertificates(authOptions *auth.AuthOptions) error { certDir := authOptions.CertDir caCertPath := authOptions.CaCertPath caPrivateKeyPath := authOptions.CaPrivateKeyPath clientCertPath := authOptions.ClientCertPath clientKeyPath := authOptions.ClientKeyPath // TODO: I'm not super happy about this use of "org", the user should // have to specify it explicitly instead of implicitly basing it on // $USER. org := mcnutils.GetUsername() bits := 2048 if _, err := os.Stat(certDir); err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(certDir, 0700); err != nil { log.Fatalf("Error creating machine certificate dir: %s", err) } } else { log.Fatal(err) } } if _, err := os.Stat(caCertPath); os.IsNotExist(err) { log.Infof("Creating CA: %s", caCertPath) // check if the key path exists; if so, error if _, err := os.Stat(caPrivateKeyPath); err == nil { log.Fatalf("The CA key already exists. Please remove it or specify a different key/cert.") } if err := GenerateCACertificate(caCertPath, caPrivateKeyPath, org, bits); err != nil { log.Infof("Error generating CA certificate: %s", err) } } if _, err := os.Stat(clientCertPath); os.IsNotExist(err) { log.Infof("Creating client certificate: %s", clientCertPath) if _, err := os.Stat(certDir); err != nil { if os.IsNotExist(err) { if err := os.Mkdir(certDir, 0700); err != nil { log.Fatalf("Error creating machine client cert dir: %s", err) } } else { log.Fatal(err) } } // check if the key path exists; if so, error if _, err := os.Stat(clientKeyPath); err == nil { log.Fatalf("The client key already exists. Please remove it or specify a different key/cert.") } if err := GenerateCert([]string{""}, clientCertPath, clientKeyPath, caCertPath, caPrivateKeyPath, org, bits); err != nil { log.Fatalf("Error generating client certificate: %s", err) } } return nil }
func (provisioner *Boot2DockerProvisioner) Provision(swarmOptions swarm.SwarmOptions, authOptions auth.AuthOptions, engineOptions engine.EngineOptions) error { const ( dockerPort = 2376 ) defer func() { ip, err := provisioner.Driver.GetIP() if err != nil { log.Fatalf("Could not get IP address for created machine: %s", err) } if conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, dockerPort), 5*time.Second); err != nil { log.Warn(` This machine has been allocated an IP address, but Docker Machine could not reach it successfully. SSH for the machine should still work, but connecting to exposed ports, such as the Docker daemon port (usually <ip>:2376), may not work properly. You may need to add the route manually, or use another related workaround. This could be due to a VPN, proxy, or host file configuration issue. You also might want to clear any VirtualBox host only interfaces you are not using.`) log.Fatal(err) } else { conn.Close() } }() provisioner.SwarmOptions = swarmOptions provisioner.AuthOptions = authOptions provisioner.EngineOptions = engineOptions if provisioner.EngineOptions.StorageDriver == "" { provisioner.EngineOptions.StorageDriver = "aufs" } if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil { return err } // b2d hosts need to wait for the daemon to be up // before continuing with provisioning if err := waitForDocker(provisioner, dockerPort); err != nil { return err } if err := makeDockerOptionsDir(provisioner); err != nil { return err } provisioner.AuthOptions = setRemoteAuthOptions(provisioner) if err := ConfigureAuth(provisioner); err != nil { return err } if err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions); err != nil { return err } return nil }