129 lines
2.8 KiB
Go
129 lines
2.8 KiB
Go
package winrmcp
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/dylanmei/iso8601"
|
|
"github.com/masterzen/winrm"
|
|
)
|
|
|
|
type Winrmcp struct {
|
|
client *winrm.Client
|
|
config *Config
|
|
}
|
|
|
|
type Config struct {
|
|
Auth Auth
|
|
Https bool
|
|
Insecure bool
|
|
TLSServerName string
|
|
CACertBytes []byte
|
|
ConnectTimeout time.Duration
|
|
OperationTimeout time.Duration
|
|
MaxOperationsPerShell int
|
|
TransportDecorator func() winrm.Transporter
|
|
}
|
|
|
|
type Auth struct {
|
|
User string
|
|
Password string
|
|
}
|
|
|
|
func New(addr string, config *Config) (*Winrmcp, error) {
|
|
endpoint, err := parseEndpoint(addr, config.Https, config.Insecure, config.TLSServerName, config.CACertBytes, config.ConnectTimeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if config == nil {
|
|
config = &Config{}
|
|
}
|
|
|
|
params := winrm.NewParameters(
|
|
winrm.DefaultParameters.Timeout,
|
|
winrm.DefaultParameters.Locale,
|
|
winrm.DefaultParameters.EnvelopeSize,
|
|
)
|
|
|
|
if config.TransportDecorator != nil {
|
|
params.TransportDecorator = config.TransportDecorator
|
|
}
|
|
|
|
if config.OperationTimeout.Seconds() > 0 {
|
|
params.Timeout = iso8601.FormatDuration(config.OperationTimeout)
|
|
}
|
|
client, err := winrm.NewClientWithParameters(
|
|
endpoint, config.Auth.User, config.Auth.Password, params)
|
|
return &Winrmcp{client, config}, err
|
|
}
|
|
|
|
func (fs *Winrmcp) Copy(fromPath, toPath string) error {
|
|
f, err := os.Open(fromPath)
|
|
if err != nil {
|
|
return fmt.Errorf("Couldn't read file %s: %v", fromPath, err)
|
|
}
|
|
|
|
defer f.Close()
|
|
fi, err := f.Stat()
|
|
if err != nil {
|
|
return fmt.Errorf("Couldn't stat file %s: %v", fromPath, err)
|
|
}
|
|
|
|
if !fi.IsDir() {
|
|
return fs.Write(toPath, f)
|
|
} else {
|
|
fw := fileWalker{
|
|
client: fs.client,
|
|
config: fs.config,
|
|
toDir: toPath,
|
|
fromDir: fromPath,
|
|
}
|
|
return filepath.Walk(fromPath, fw.copyFile)
|
|
}
|
|
}
|
|
|
|
func (fs *Winrmcp) Write(toPath string, src io.Reader) error {
|
|
return doCopy(fs.client, fs.config, src, winPath(toPath))
|
|
}
|
|
|
|
func (fs *Winrmcp) List(remotePath string) ([]FileItem, error) {
|
|
return fetchList(fs.client, winPath(remotePath))
|
|
}
|
|
|
|
type fileWalker struct {
|
|
client *winrm.Client
|
|
config *Config
|
|
toDir string
|
|
fromDir string
|
|
}
|
|
|
|
func (fw *fileWalker) copyFile(fromPath string, fi os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !shouldUploadFile(fi) {
|
|
return nil
|
|
}
|
|
|
|
hostPath, _ := filepath.Abs(fromPath)
|
|
fromDir, _ := filepath.Abs(fw.fromDir)
|
|
relPath, _ := filepath.Rel(fromDir, hostPath)
|
|
toPath := filepath.Join(fw.toDir, relPath)
|
|
|
|
f, err := os.Open(hostPath)
|
|
if err != nil {
|
|
return fmt.Errorf("Couldn't read file %s: %v", fromPath, err)
|
|
}
|
|
|
|
return doCopy(fw.client, fw.config, f, winPath(toPath))
|
|
}
|
|
|
|
func shouldUploadFile(fi os.FileInfo) bool {
|
|
// Ignore dir entries and OS X special hidden file
|
|
return !fi.IsDir() && ".DS_Store" != fi.Name()
|
|
}
|