mirror of
https://github.com/appleboy/drone-scp.git
synced 2026-06-16 14:49:20 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0745e13d39 | |||
| f1301199ca | |||
| 6fd87e0460 | |||
| cf09357b85 |
@@ -264,6 +264,11 @@ func main() {
|
|||||||
Usage: "use --unlink-first flag with tar",
|
Usage: "use --unlink-first flag with tar",
|
||||||
EnvVars: []string{"PLUGIN_UNLINK_FIRST", "SCP_UNLINK_FIRST", "INPUT_UNLINK_FIRST"},
|
EnvVars: []string{"PLUGIN_UNLINK_FIRST", "SCP_UNLINK_FIRST", "INPUT_UNLINK_FIRST"},
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "tar.dereference",
|
||||||
|
Usage: "use --dereference flag with tar",
|
||||||
|
EnvVars: []string{"PLUGIN_TAR_DEREFERENCE", "SCP_TAR_DEREFERENCE", "INPUT_TAR_DEREFERENCE"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override a template
|
// Override a template
|
||||||
@@ -342,6 +347,7 @@ func run(c *cli.Context) error {
|
|||||||
UnlinkFirst: c.Bool("unlink.first"),
|
UnlinkFirst: c.Bool("unlink.first"),
|
||||||
Ciphers: c.StringSlice("ciphers"),
|
Ciphers: c.StringSlice("ciphers"),
|
||||||
UseInsecureCipher: c.Bool("useInsecureCipher"),
|
UseInsecureCipher: c.Bool("useInsecureCipher"),
|
||||||
|
TarDereference: c.Bool("tar.dereference"),
|
||||||
Proxy: easyssh.DefaultConfig{
|
Proxy: easyssh.DefaultConfig{
|
||||||
Key: c.String("proxy.ssh-key"),
|
Key: c.String("proxy.ssh-key"),
|
||||||
Passphrase: c.String("proxy.ssh-passphrase"),
|
Passphrase: c.String("proxy.ssh-passphrase"),
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import (
|
|||||||
var (
|
var (
|
||||||
errMissingHost = errors.New("Error: missing server host")
|
errMissingHost = errors.New("Error: missing server host")
|
||||||
errMissingPasswordOrKey = errors.New("Error: can't connect without a private SSH key or password")
|
errMissingPasswordOrKey = errors.New("Error: can't connect without a private SSH key or password")
|
||||||
errSetPasswordandKey = errors.New("can't set password and key at the same time")
|
|
||||||
errMissingSourceOrTarget = errors.New("missing source or target config")
|
errMissingSourceOrTarget = errors.New("missing source or target config")
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,6 +65,7 @@ type (
|
|||||||
UnlinkFirst bool
|
UnlinkFirst bool
|
||||||
Ciphers []string
|
Ciphers []string
|
||||||
UseInsecureCipher bool
|
UseInsecureCipher bool
|
||||||
|
TarDereference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin values.
|
// Plugin values.
|
||||||
@@ -91,7 +91,7 @@ func globList(paths []string) fileList {
|
|||||||
|
|
||||||
for _, pattern := range paths {
|
for _, pattern := range paths {
|
||||||
ignore := false
|
ignore := false
|
||||||
pattern = strings.Trim(pattern, " ")
|
pattern = strings.TrimSpace(pattern)
|
||||||
if string(pattern[0]) == "!" {
|
if string(pattern[0]) == "!" {
|
||||||
pattern = pattern[1:]
|
pattern = pattern[1:]
|
||||||
ignore = true
|
ignore = true
|
||||||
@@ -112,21 +112,6 @@ func globList(paths []string) fileList {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildArgs(tar string, files fileList) []string {
|
|
||||||
args := []string{}
|
|
||||||
if len(files.Ignore) > 0 {
|
|
||||||
for _, v := range files.Ignore {
|
|
||||||
args = append(args, "--exclude")
|
|
||||||
args = append(args, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args = append(args, "-zcf")
|
|
||||||
args = append(args, getRealPath(tar))
|
|
||||||
args = append(args, files.Source...)
|
|
||||||
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Plugin) log(host string, message ...interface{}) {
|
func (p Plugin) log(host string, message ...interface{}) {
|
||||||
if count := len(p.Config.Host); count == 1 {
|
if count := len(p.Config.Host); count == 1 {
|
||||||
fmt.Printf("%s", fmt.Sprintln(message...))
|
fmt.Printf("%s", fmt.Sprintln(message...))
|
||||||
@@ -204,12 +189,33 @@ type fileList struct {
|
|||||||
Source []string
|
Source []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Plugin) buildArgs(target string) []string {
|
func (p *Plugin) buildTarArgs(src string) []string {
|
||||||
|
files := globList(trimValues(p.Config.Source))
|
||||||
|
args := []string{}
|
||||||
|
if len(files.Ignore) > 0 {
|
||||||
|
for _, v := range files.Ignore {
|
||||||
|
args = append(args, "--exclude")
|
||||||
|
args = append(args, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Config.TarDereference {
|
||||||
|
args = append(args, "--dereference")
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, "-zcf")
|
||||||
|
args = append(args, getRealPath(src))
|
||||||
|
args = append(args, files.Source...)
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) buildUnTarArgs(target string) []string {
|
||||||
args := []string{}
|
args := []string{}
|
||||||
|
|
||||||
args = append(args,
|
args = append(args,
|
||||||
p.Config.TarExec,
|
p.Config.TarExec,
|
||||||
"-xf",
|
"-zxf",
|
||||||
p.DestFile,
|
p.DestFile,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -236,33 +242,28 @@ func (p *Plugin) buildArgs(target string) []string {
|
|||||||
|
|
||||||
// Exec executes the plugin.
|
// Exec executes the plugin.
|
||||||
func (p *Plugin) Exec() error {
|
func (p *Plugin) Exec() error {
|
||||||
hosts := trimValues(p.Config.Host)
|
|
||||||
if len(hosts) == 0 {
|
|
||||||
return errMissingHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p.Config.Key) == 0 && len(p.Config.Password) == 0 && len(p.Config.KeyPath) == 0 {
|
if len(p.Config.Key) == 0 && len(p.Config.Password) == 0 && len(p.Config.KeyPath) == 0 {
|
||||||
return errMissingPasswordOrKey
|
return errMissingPasswordOrKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.Config.Key) != 0 && len(p.Config.Password) != 0 {
|
|
||||||
return errSetPasswordandKey
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p.Config.Source) == 0 || len(p.Config.Target) == 0 {
|
if len(p.Config.Source) == 0 || len(p.Config.Target) == 0 {
|
||||||
return errMissingSourceOrTarget
|
return errMissingSourceOrTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
files := globList(trimValues(p.Config.Source))
|
hosts := trimValues(p.Config.Host)
|
||||||
|
if len(hosts) == 0 {
|
||||||
|
return errMissingHost
|
||||||
|
}
|
||||||
|
|
||||||
p.DestFile = fmt.Sprintf("%s.tar.gz", random.String(10))
|
p.DestFile = fmt.Sprintf("%s.tar.gz", random.String(10))
|
||||||
|
|
||||||
// create a temporary file for the archive
|
// create a temporary file for the archive
|
||||||
dir := os.TempDir()
|
dir := os.TempDir()
|
||||||
tar := filepath.Join(dir, p.DestFile)
|
src := filepath.Join(dir, p.DestFile)
|
||||||
|
|
||||||
// run archive command
|
// run archive command
|
||||||
fmt.Println("tar all files into " + tar)
|
fmt.Println("tar all files into " + src)
|
||||||
args := buildArgs(tar, files)
|
args := p.buildTarArgs(src)
|
||||||
cmd := exec.Command(p.Config.TarExec, args...)
|
cmd := exec.Command(p.Config.TarExec, args...)
|
||||||
if p.Config.Debug {
|
if p.Config.Debug {
|
||||||
fmt.Println("$", strings.Join(cmd.Args, " "))
|
fmt.Println("$", strings.Join(cmd.Args, " "))
|
||||||
@@ -324,7 +325,7 @@ func (p *Plugin) Exec() error {
|
|||||||
|
|
||||||
// Call Scp method with file you want to upload to remote server.
|
// Call Scp method with file you want to upload to remote server.
|
||||||
p.log(host, "scp file to server.")
|
p.log(host, "scp file to server.")
|
||||||
err = ssh.Scp(tar, p.DestFile)
|
err = ssh.Scp(src, p.DestFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChannel <- copyError{host, err.Error()}
|
errChannel <- copyError{host, err.Error()}
|
||||||
return
|
return
|
||||||
@@ -356,7 +357,7 @@ func (p *Plugin) Exec() error {
|
|||||||
|
|
||||||
// untar file
|
// untar file
|
||||||
p.log(host, "untar file", p.DestFile)
|
p.log(host, "untar file", p.DestFile)
|
||||||
commamd := strings.Join(p.buildArgs(target), " ")
|
commamd := strings.Join(p.buildUnTarArgs(target), " ")
|
||||||
if p.Config.Debug {
|
if p.Config.Debug {
|
||||||
fmt.Println("$", commamd)
|
fmt.Println("$", commamd)
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-72
@@ -51,23 +51,6 @@ func TestMissingSourceConfig(t *testing.T) {
|
|||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetPasswordAndKey(t *testing.T) {
|
|
||||||
plugin := Plugin{
|
|
||||||
Config: Config{
|
|
||||||
Host: []string{"example.com"},
|
|
||||||
Username: "ubuntu",
|
|
||||||
Port: "443",
|
|
||||||
Password: "1234",
|
|
||||||
Key: "test",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := plugin.Exec()
|
|
||||||
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
assert.Equal(t, errSetPasswordandKey, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTrimElement(t *testing.T) {
|
func TestTrimElement(t *testing.T) {
|
||||||
var input, result []string
|
var input, result []string
|
||||||
|
|
||||||
@@ -572,25 +555,6 @@ func TestGlobList(t *testing.T) {
|
|||||||
assert.Equal(t, expectIgnores, result.Ignore)
|
assert.Equal(t, expectIgnores, result.Ignore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildArgs(t *testing.T) {
|
|
||||||
list := fileList{
|
|
||||||
Source: []string{"tests/a.txt", "tests/b.txt", "tests/c.txt"},
|
|
||||||
Ignore: []string{"tests/a.txt", "tests/b.txt"},
|
|
||||||
}
|
|
||||||
|
|
||||||
result := buildArgs("test.tar.gz", list)
|
|
||||||
expects := []string{"--exclude", "tests/a.txt", "--exclude", "tests/b.txt", "-zcf", "test.tar.gz", "tests/a.txt", "tests/b.txt", "tests/c.txt"}
|
|
||||||
assert.Equal(t, expects, result)
|
|
||||||
|
|
||||||
list = fileList{
|
|
||||||
Source: []string{"tests/a.txt", "tests/b.txt"},
|
|
||||||
}
|
|
||||||
|
|
||||||
result = buildArgs("test.tar.gz", list)
|
|
||||||
expects = []string{"-zcf", "test.tar.gz", "tests/a.txt", "tests/b.txt"}
|
|
||||||
assert.Equal(t, expects, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveDestFile(t *testing.T) {
|
func TestRemoveDestFile(t *testing.T) {
|
||||||
ssh := &easyssh.MakeConfig{
|
ssh := &easyssh.MakeConfig{
|
||||||
Server: "localhost",
|
Server: "localhost",
|
||||||
@@ -629,7 +593,7 @@ func TestRemoveDestFile(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPlugin_buildArgs(t *testing.T) {
|
func TestPlugin_buildUnTarArgs(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
Repo Repo
|
Repo Repo
|
||||||
Build Build
|
Build Build
|
||||||
@@ -653,12 +617,12 @@ func TestPlugin_buildArgs(t *testing.T) {
|
|||||||
UnlinkFirst: false,
|
UnlinkFirst: false,
|
||||||
TarExec: "tar",
|
TarExec: "tar",
|
||||||
},
|
},
|
||||||
DestFile: "foo.tar",
|
DestFile: "foo.tar.gz",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
target: "foo",
|
target: "foo",
|
||||||
},
|
},
|
||||||
want: []string{"tar", "-xf", "foo.tar", "-C", "foo"},
|
want: []string{"tar", "-zxf", "foo.tar.gz", "-C", "foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strip components",
|
name: "strip components",
|
||||||
@@ -669,12 +633,12 @@ func TestPlugin_buildArgs(t *testing.T) {
|
|||||||
TarExec: "tar",
|
TarExec: "tar",
|
||||||
StripComponents: 2,
|
StripComponents: 2,
|
||||||
},
|
},
|
||||||
DestFile: "foo.tar",
|
DestFile: "foo.tar.gz",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
target: "foo",
|
target: "foo",
|
||||||
},
|
},
|
||||||
want: []string{"tar", "-xf", "foo.tar", "--strip-components", "2", "-C", "foo"},
|
want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "-C", "foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "overwrite",
|
name: "overwrite",
|
||||||
@@ -685,12 +649,12 @@ func TestPlugin_buildArgs(t *testing.T) {
|
|||||||
Overwrite: true,
|
Overwrite: true,
|
||||||
UnlinkFirst: false,
|
UnlinkFirst: false,
|
||||||
},
|
},
|
||||||
DestFile: "foo.tar",
|
DestFile: "foo.tar.gz",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
target: "foo",
|
target: "foo",
|
||||||
},
|
},
|
||||||
want: []string{"tar", "-xf", "foo.tar", "--strip-components", "2", "--overwrite", "-C", "foo"},
|
want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "--overwrite", "-C", "foo"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unlink first",
|
name: "unlink first",
|
||||||
@@ -701,12 +665,12 @@ func TestPlugin_buildArgs(t *testing.T) {
|
|||||||
Overwrite: true,
|
Overwrite: true,
|
||||||
UnlinkFirst: true,
|
UnlinkFirst: true,
|
||||||
},
|
},
|
||||||
DestFile: "foo.tar",
|
DestFile: "foo.tar.gz",
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
target: "foo",
|
target: "foo",
|
||||||
},
|
},
|
||||||
want: []string{"tar", "-xf", "foo.tar", "--strip-components", "2", "--overwrite", "--unlink-first", "-C", "foo"},
|
want: []string{"tar", "-zxf", "foo.tar.gz", "--strip-components", "2", "--overwrite", "--unlink-first", "-C", "foo"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -717,41 +681,80 @@ func TestPlugin_buildArgs(t *testing.T) {
|
|||||||
Config: tt.fields.Config,
|
Config: tt.fields.Config,
|
||||||
DestFile: tt.fields.DestFile,
|
DestFile: tt.fields.DestFile,
|
||||||
}
|
}
|
||||||
if got := p.buildArgs(tt.args.target); !reflect.DeepEqual(got, tt.want) {
|
if got := p.buildUnTarArgs(tt.args.target); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("Plugin.buildArgs() = %v, want %v", got, tt.want)
|
t.Errorf("Plugin.buildArgs() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckTargetFolderExist(t *testing.T) {
|
func TestPlugin_buildTarArgs(t *testing.T) {
|
||||||
if os.Getenv("SSH_AUTH_SOCK") != "" {
|
type fields struct {
|
||||||
if err := exec.Command("eval", "`ssh-agent -k`").Run(); err != nil {
|
Config Config
|
||||||
t.Fatalf("exec: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
type args struct {
|
||||||
u, err := user.Lookup("drone-scp")
|
src string
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Lookup: %v", err)
|
|
||||||
}
|
}
|
||||||
|
tests := []struct {
|
||||||
plugin := Plugin{
|
name string
|
||||||
Config: Config{
|
fields fields
|
||||||
Host: []string{"localhost"},
|
args args
|
||||||
Username: "drone-scp",
|
want []string
|
||||||
Port: "22",
|
}{
|
||||||
KeyPath: "tests/.ssh/id_rsa",
|
{
|
||||||
Source: []string{"tests/global/*"},
|
name: "default command",
|
||||||
Target: []string{filepath.Join(u.HomeDir, "__test__")},
|
fields: fields{
|
||||||
CommandTimeout: 60 * time.Second,
|
Config: Config{
|
||||||
TarExec: "tar",
|
TarExec: "tar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
src: "foo.tar.gz",
|
||||||
|
},
|
||||||
|
want: []string{"-zcf", "foo.tar.gz"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ignore list",
|
||||||
|
fields: fields{
|
||||||
|
Config: Config{
|
||||||
|
TarExec: "tar",
|
||||||
|
Source: []string{
|
||||||
|
"tests/*.txt",
|
||||||
|
"!tests/a.txt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
src: "foo.tar.gz",
|
||||||
|
},
|
||||||
|
want: []string{"--exclude", "tests/a.txt", "-zcf", "foo.tar.gz", "tests/a.txt", "tests/b.txt"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "dereference flag",
|
||||||
|
fields: fields{
|
||||||
|
Config: Config{
|
||||||
|
TarExec: "tar",
|
||||||
|
TarDereference: true,
|
||||||
|
Source: []string{
|
||||||
|
"tests/*.txt",
|
||||||
|
"!tests/a.txt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
src: "foo.tar.gz",
|
||||||
|
},
|
||||||
|
want: []string{"--exclude", "tests/a.txt", "--dereference", "-zcf", "foo.tar.gz", "tests/a.txt", "tests/b.txt"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
err = plugin.Exec()
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
p := &Plugin{
|
||||||
|
Config: tt.fields.Config,
|
||||||
err = plugin.Exec()
|
}
|
||||||
assert.Nil(t, err)
|
if got := p.buildTarArgs(tt.args.src); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Plugin.buildTarArgs() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user