Skip to content

Commit

Permalink
Fix the wrong arch of target host (#524)
Browse files Browse the repository at this point in the history
* Fix the wrong arch of target host,
* get the OS arch with `uname -a`
* refactor the SSHConnectionTimeout constant
* only provision on remote host
  • Loading branch information
metrue authored May 7, 2020
1 parent 3923c34 commit 5ce61ef
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 67 deletions.
41 changes: 28 additions & 13 deletions middlewares/driver.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package middlewares

import (
"bytes"
"fmt"
"runtime"
"strings"
"time"

"github.com/apex/log"
Expand All @@ -12,7 +13,7 @@ import (
dockerDriver "github.com/metrue/fx/driver/docker"
k8sInfra "github.com/metrue/fx/driver/k8s"
"github.com/metrue/fx/provisioner"
darwin "github.com/metrue/fx/provisioner/darwin"
"github.com/metrue/fx/provisioner/darwin"
linux "github.com/metrue/fx/provisioner/linux"
"github.com/metrue/go-ssh-client"
)
Expand All @@ -32,20 +33,34 @@ func Driver(ctx context.Contexter) (err error) {
if err := driver.Ping(ctx.GetContext()); err != nil {
log.Infof("provisioning %s ...", host)

var provisioner provisioner.Provisioner
// TODO actually we should get os of target host, not the host of fx
// running on
if runtime.GOOS == "darwin" {
provisioner = darwin.New(sshClient)
} else {
provisioner = linux.New(sshClient)
}
isRemote := (host != "127.0.0.1" && host != "localhost")
if err := provisioner.Provision(ctx.GetContext(), isRemote); err != nil {
return err
hostOS := "linux"
if isRemote {
ok, err := sshClient.Connectable(provisioner.SSHConnectionTimeout)
if err != nil {
return err
}
if !ok {
return fmt.Errorf("target host could not be connected with SSH")
}

var buf bytes.Buffer
if err := sshClient.RunCommand("uname -a", ssh.CommandOptions{Stdout: &buf}); err != nil {
return err
}
hostOS = buf.String()
}
if strings.Contains(hostOS, "darwin") {
if err := darwin.New(sshClient).Provision(ctx.GetContext(), isRemote); err != nil {
return err
}
} else {
if err := linux.New(sshClient).Provision(ctx.GetContext(), isRemote); err != nil {
return err
}
}
time.Sleep(2 * time.Second)
}
time.Sleep(2 * time.Second)
if err := docker.Initialize(); err != nil {
return fmt.Errorf("initialize docker client failed: %s", err)
}
Expand Down
3 changes: 2 additions & 1 deletion middlewares/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ users:
defer os.Remove(kubeconf.Name())

sshClient := sshMocks.NewMockClienter(ctrl)
sshClient.EXPECT().Connectable(10*time.Second).Return(true, nil).Times(2)
sshClient.EXPECT().Connectable(10*time.Second).Return(true, nil).Times(3)
sshClient.EXPECT().RunCommand("uname -a", gomock.Any()).Return(nil)
sshClient.EXPECT().RunCommand("docker version", ssh.CommandOptions{
Timeout: 10 * time.Second,
}).Return(nil)
Expand Down
1 change: 0 additions & 1 deletion middlewares/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ func set(ctx context.Contexter, cli *cli.Context, fields []argsField) error {
ctx.Set("host", ip)
ctx.Set("user", user)
} else {

ctx.Set(f.Name, cli.String(f.Name))
}
} else if f.Type == "int" {
Expand Down
7 changes: 2 additions & 5 deletions provisioner/darwin/darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ import (
"fmt"
"os/exec"
"strings"
"time"

"github.com/metrue/fx/provisioner"
"github.com/metrue/go-ssh-client"
)

const sshConnectionTimeout = 10 * time.Second

var scripts = map[string]string{
"docker_version": "docker version",
"has_docker": "type docker",
Expand Down Expand Up @@ -52,7 +49,7 @@ func (d *Docker) Provision(ctx context.Context, isRemote bool) error {

func (d *Docker) runCmd(script string, isRemote bool, options ...ssh.CommandOptions) error {
option := ssh.CommandOptions{
Timeout: sshConnectionTimeout,
Timeout: provisioner.SSHConnectionTimeout,
}
if len(options) >= 1 {
option = options[0]
Expand All @@ -72,7 +69,7 @@ func (d *Docker) runCmd(script string, isRemote bool, options ...ssh.CommandOpti
}
return nil
}
ok, err := d.sshClient.Connectable(sshConnectionTimeout)
ok, err := d.sshClient.Connectable(provisioner.SSHConnectionTimeout)
if err != nil {
return fmt.Errorf("could not connect via SSH: '%s'", err)
}
Expand Down
35 changes: 18 additions & 17 deletions provisioner/darwin/darwin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/golang/mock/gomock"
"github.com/metrue/fx/provisioner"
"github.com/metrue/go-ssh-client"
sshMocks "github.com/metrue/go-ssh-client/mocks"
)
Expand All @@ -18,7 +19,7 @@ func TestDriverProvision(t *testing.T) {
sshClient := sshMocks.NewMockClienter(ctrl)
n := &Docker{sshClient: sshClient}
err := errors.New("could not connect to host")
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(false, err).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(false, err).AnyTimes()
if err := n.Provision(context.Background(), true); err == nil {
t.Fatalf("should get error when SSH connection not ok")
}
Expand All @@ -30,7 +31,7 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(false, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(false, nil).AnyTimes()
if err := n.Provision(context.Background(), true); err == nil {
t.Fatalf("should get error when SSH connection not ok")
}
Expand All @@ -42,9 +43,9 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -56,10 +57,10 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
err := errors.New("docker command not found")
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["has_docker"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["has_docker"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
if err := n.Provision(context.Background(), true); err == nil {
t.Fatal("should tell user to install docker first")
}
Expand All @@ -71,11 +72,11 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
err := errors.New("fx agent not found")
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -88,9 +89,9 @@ func TestDriverProvision(t *testing.T) {
sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)

sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"], ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -107,9 +108,9 @@ func TestRunCommand(t *testing.T) {
}
script := "script"
option := ssh.CommandOptions{
Timeout: sshConnectionTimeout,
Timeout: provisioner.SSHConnectionTimeout,
}
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil)
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil)
sshClient.EXPECT().RunCommand(script, option).Return(nil)
if err := n.runCmd(script, true, option); err != nil {
t.Fatal(err)
Expand Down
7 changes: 2 additions & 5 deletions provisioner/linux/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import (
"fmt"
"os/exec"
"strings"
"time"

"github.com/metrue/fx/provisioner"
"github.com/metrue/go-ssh-client"
)

const sshConnectionTimeout = 10 * time.Second

var scripts = map[string]interface{}{
"docker_version": "docker version",
"has_docker": "type docker",
Expand Down Expand Up @@ -58,7 +55,7 @@ func (d *Docker) Provision(ctx context.Context, isRemote bool) error {

func (d *Docker) runCmd(script string, isRemote bool, options ...ssh.CommandOptions) error {
option := ssh.CommandOptions{
Timeout: sshConnectionTimeout,
Timeout: provisioner.SSHConnectionTimeout,
}
if len(options) >= 1 {
option = options[0]
Expand All @@ -78,7 +75,7 @@ func (d *Docker) runCmd(script string, isRemote bool, options ...ssh.CommandOpti
}
return nil
}
ok, err := d.sshClient.Connectable(sshConnectionTimeout)
ok, err := d.sshClient.Connectable(provisioner.SSHConnectionTimeout)
if err != nil {
return fmt.Errorf("could not connect via SSH: '%s'", err)
}
Expand Down
49 changes: 25 additions & 24 deletions provisioner/linux/linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/golang/mock/gomock"
"github.com/metrue/fx/provisioner"
"github.com/metrue/go-ssh-client"
sshMocks "github.com/metrue/go-ssh-client/mocks"
)
Expand All @@ -18,7 +19,7 @@ func TestDriverProvision(t *testing.T) {
sshClient := sshMocks.NewMockClienter(ctrl)
n := &Docker{sshClient: sshClient}
err := errors.New("could not connect to host")
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(false, err).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(false, err).AnyTimes()
if err := n.Provision(context.Background(), true); err == nil {
t.Fatalf("should get error when SSH connection not ok")
}
Expand All @@ -30,7 +31,7 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(false, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(false, nil).AnyTimes()
if err := n.Provision(context.Background(), true); err == nil {
t.Fatalf("should get error when SSH connection not ok")
}
Expand All @@ -42,9 +43,9 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -56,13 +57,13 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
err := errors.New("docker command not found")
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["has_docker"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["install_docker"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["start_dockerd"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["has_docker"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["install_docker"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["start_dockerd"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -74,11 +75,11 @@ func TestDriverProvision(t *testing.T) {

sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
err := errors.New("fx agent not found")
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -91,15 +92,15 @@ func TestDriverProvision(t *testing.T) {
sshClient := sshMocks.NewMockClienter(ctrl)
n := New(sshClient)

sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil).AnyTimes()
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil).AnyTimes()
err2 := errors.New("fx agent not found")
err1 := errors.New("docker command not found")
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err1)
sshClient.EXPECT().RunCommand(scripts["has_docker"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err1)
sshClient.EXPECT().RunCommand(scripts["install_docker"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["start_dockerd"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(err2)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"].(string), ssh.CommandOptions{Timeout: sshConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["docker_version"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err1)
sshClient.EXPECT().RunCommand(scripts["has_docker"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err1)
sshClient.EXPECT().RunCommand(scripts["install_docker"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["start_dockerd"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
sshClient.EXPECT().RunCommand(scripts["check_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(err2)
sshClient.EXPECT().RunCommand(scripts["start_fx_agent"].(string), ssh.CommandOptions{Timeout: provisioner.SSHConnectionTimeout}).Return(nil)
if err := n.Provision(context.Background(), true); err != nil {
t.Fatal(err)
}
Expand All @@ -116,9 +117,9 @@ func TestRunCommand(t *testing.T) {
}
script := "script"
option := ssh.CommandOptions{
Timeout: sshConnectionTimeout,
Timeout: provisioner.SSHConnectionTimeout,
}
sshClient.EXPECT().Connectable(sshConnectionTimeout).Return(true, nil)
sshClient.EXPECT().Connectable(provisioner.SSHConnectionTimeout).Return(true, nil)
sshClient.EXPECT().RunCommand(script, option).Return(nil)
if err := n.runCmd(script, true, option); err != nil {
t.Fatal(err)
Expand Down
8 changes: 7 additions & 1 deletion provisioner/provisioner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package provisioner

import "context"
import (
"context"
"time"
)

// SSHConnectionTimeout default timeout for ssh connection
const SSHConnectionTimeout = 10 * time.Second

// Provisioner define provisioner interface
type Provisioner interface {
Expand Down

0 comments on commit 5ce61ef

Please sign in to comment.