forked from toolshed/abra
		
	fix: working provisioning post chaos testing
This commit is contained in:
		@ -19,7 +19,6 @@ import (
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/swarm"
 | 
			
		||||
	dockerClient "github.com/docker/docker/client"
 | 
			
		||||
	"github.com/sfreiberg/simplessh"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
	"github.com/urfave/cli/v2"
 | 
			
		||||
)
 | 
			
		||||
@ -155,8 +154,22 @@ func newClient(c *cli.Context, domainName string) (*dockerClient.Client, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func installDocker(c *cli.Context, cl *dockerClient.Client, domainName string) error {
 | 
			
		||||
	if _, err := cl.Info(c.Context); err != nil {
 | 
			
		||||
		if strings.Contains(err.Error(), "command not found") {
 | 
			
		||||
	logrus.Debugf("attempting to construct SSH client for %s", domainName)
 | 
			
		||||
 | 
			
		||||
	client, err := ssh.New(domainName, sshAuth)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer client.Close()
 | 
			
		||||
 | 
			
		||||
	logrus.Debugf("successfully created SSH client for %s", domainName)
 | 
			
		||||
 | 
			
		||||
	result, err := client.Exec("which docker")
 | 
			
		||||
	if err != nil && string(result) != "" {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if string(result) == "" {
 | 
			
		||||
		fmt.Println(fmt.Sprintf(`
 | 
			
		||||
A docker installation cannot be found on %s. This is a required system dependency
 | 
			
		||||
for running Co-op Cloud on your server. If you would like, Abra can attempt to install
 | 
			
		||||
@ -185,42 +198,6 @@ source for this script can be seen here:
 | 
			
		||||
			logrus.Fatal("exiting as requested")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			hasIdentityFile := true
 | 
			
		||||
			if sshAuth == "password" {
 | 
			
		||||
				hasIdentityFile = false
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			hostConfig, err := ssh.GetHostConfig(domainName, hasIdentityFile)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var client *simplessh.Client
 | 
			
		||||
			if sshAuth == "identity-file" {
 | 
			
		||||
				var err error
 | 
			
		||||
				client, err = simplessh.ConnectWithAgent(hostConfig.Host, hostConfig.User)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				password := ""
 | 
			
		||||
				prompt := &survey.Password{
 | 
			
		||||
					Message: "SSH password?",
 | 
			
		||||
				}
 | 
			
		||||
				if err := survey.AskOne(prompt, &password); err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var err error
 | 
			
		||||
				client, err = simplessh.ConnectWithPassword(hostConfig.Host, hostConfig.User, password)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			defer client.Close()
 | 
			
		||||
			logrus.Debugf("successfully created SSH client for %s", domainName)
 | 
			
		||||
 | 
			
		||||
		cmd := "curl -s https://get.docker.com | bash"
 | 
			
		||||
 | 
			
		||||
		var sudoPass string
 | 
			
		||||
@ -243,12 +220,10 @@ source for this script can be seen here:
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			logrus.Infof("docker has successfully been installed on %s", domainName)
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	logrus.Infof("docker is installed on %s", domainName)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -381,12 +356,7 @@ You may omit flags to avoid performing this provisioning logic.
 | 
			
		||||
	},
 | 
			
		||||
	ArgsUsage: "<domain> [<user>] [<port>]",
 | 
			
		||||
	Action: func(c *cli.Context) error {
 | 
			
		||||
		if c.Args().Len() == 2 && !local {
 | 
			
		||||
			err := errors.New("missing arguments <domain> or '--local'")
 | 
			
		||||
			internal.ShowSubcommandHelpAndError(c, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if c.Args().Get(2) != "" && local {
 | 
			
		||||
		if c.Args().Len() > 0 && local {
 | 
			
		||||
			err := errors.New("cannot use '<domain>' and '--local' together")
 | 
			
		||||
			internal.ShowSubcommandHelpAndError(c, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -84,6 +84,18 @@ Your new Hetzner Cloud VPS has successfully been created! Here are the details:
 | 
			
		||||
    VPS IP address: %s
 | 
			
		||||
    VPS Root Password: %s
 | 
			
		||||
 | 
			
		||||
Here is what your SSH configuration (~/.ssh/config) might look like:
 | 
			
		||||
 | 
			
		||||
    Host %s.example.com
 | 
			
		||||
      Hostname %s
 | 
			
		||||
      User root
 | 
			
		||||
      Port 22
 | 
			
		||||
      IdentityFile ~/.ssh/<your-ssh-private-key>
 | 
			
		||||
 | 
			
		||||
Remember, your "Host" value must be a valid publicly accessible domain name as
 | 
			
		||||
Abra uses this domain to identity servers. If you specified "--ssh-auth
 | 
			
		||||
password" then you may skip the IdentityFile stanza.
 | 
			
		||||
 | 
			
		||||
You can access this new VPS via SSH using the following command:
 | 
			
		||||
 | 
			
		||||
    ssh root@%s
 | 
			
		||||
@ -92,7 +104,11 @@ Please note, this server is not managed by Abra yet (i.e. "abra server ls" will
 | 
			
		||||
not list this server)! You will need to assign a domain name record ("abra
 | 
			
		||||
record new") and add the server to your Abra configuration ("abra server add")
 | 
			
		||||
to have a working server that you can deploy Co-op Cloud apps to.
 | 
			
		||||
	`, internal.HetznerCloudName, ip, rootPassword, ip))
 | 
			
		||||
	`,
 | 
			
		||||
		internal.HetznerCloudName, ip, rootPassword,
 | 
			
		||||
		internal.HetznerCloudName, ip,
 | 
			
		||||
		ip,
 | 
			
		||||
	))
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,12 @@ package ssh
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/user"
 | 
			
		||||
 | 
			
		||||
	"github.com/AlecAivazis/survey/v2"
 | 
			
		||||
	"github.com/kevinburke/ssh_config"
 | 
			
		||||
	"github.com/sfreiberg/simplessh"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// HostConfig is a SSH host config.
 | 
			
		||||
@ -18,28 +22,78 @@ type HostConfig struct {
 | 
			
		||||
func GetHostConfig(hostname string, hasIdentityFile bool) (HostConfig, error) {
 | 
			
		||||
	var hostConfig HostConfig
 | 
			
		||||
 | 
			
		||||
	var host, user, port, idf string
 | 
			
		||||
	var host, sshUser, port, idf string
 | 
			
		||||
 | 
			
		||||
	if host = ssh_config.Get(hostname, "Hostname"); host == "" {
 | 
			
		||||
		return hostConfig, fmt.Errorf("SSH hostname missing for %s from SSH config", hostname)
 | 
			
		||||
		logrus.Debugf("no hostname found in SSH config, assuming %s", hostname)
 | 
			
		||||
		host = hostname
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if user = ssh_config.Get(hostname, "User"); user == "" {
 | 
			
		||||
		return hostConfig, fmt.Errorf("SSH user missing for %s from SSH config", hostname)
 | 
			
		||||
	if sshUser = ssh_config.Get(hostname, "User"); sshUser == "" {
 | 
			
		||||
		systemUser, err := user.Current()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return hostConfig, err
 | 
			
		||||
		}
 | 
			
		||||
		username := systemUser.Username
 | 
			
		||||
		logrus.Debugf("no username found in SSH config, assuming %s", username)
 | 
			
		||||
		sshUser = username
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if port = ssh_config.Get(hostname, "Port"); port == "" {
 | 
			
		||||
		return hostConfig, fmt.Errorf("SSH port missing for %s from SSH config", hostname)
 | 
			
		||||
		logrus.Debugf("no port found in SSH config, assuming 22")
 | 
			
		||||
		port = "22"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if idf = ssh_config.Get(hostname, "IdentityFile"); idf == "" && hasIdentityFile {
 | 
			
		||||
	dummyVal := "~/.ssh/identity"
 | 
			
		||||
	if idf = ssh_config.Get(hostname, "IdentityFile"); (idf == dummyVal || idf == "") && hasIdentityFile {
 | 
			
		||||
		return hostConfig, fmt.Errorf("SSH identity file missing for %s from SSH config", hostname)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hostConfig.Host = host
 | 
			
		||||
	hostConfig.IdentityFile = idf
 | 
			
		||||
	hostConfig.Port = port
 | 
			
		||||
	hostConfig.User = user
 | 
			
		||||
	hostConfig.User = sshUser
 | 
			
		||||
 | 
			
		||||
	logrus.Debugf("constructed SSH config %s for %s", hostConfig, hostname)
 | 
			
		||||
 | 
			
		||||
	return hostConfig, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New creates a new SSH client connection.
 | 
			
		||||
func New(domainName, sshAuth string) (*simplessh.Client, error) {
 | 
			
		||||
	var client *simplessh.Client
 | 
			
		||||
 | 
			
		||||
	hasIdentityFile := true
 | 
			
		||||
	if sshAuth == "password" {
 | 
			
		||||
		hasIdentityFile = false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hostConfig, err := GetHostConfig(domainName, hasIdentityFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return client, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if sshAuth == "identity-file" {
 | 
			
		||||
		var err error
 | 
			
		||||
		client, err = simplessh.ConnectWithAgent(hostConfig.Host, hostConfig.User)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return client, err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		password := ""
 | 
			
		||||
		prompt := &survey.Password{
 | 
			
		||||
			Message: "SSH password?",
 | 
			
		||||
		}
 | 
			
		||||
		if err := survey.AskOne(prompt, &password); err != nil {
 | 
			
		||||
			return client, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		client, err = simplessh.ConnectWithPassword(hostConfig.Host, hostConfig.User, password)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return client, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return client, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user