Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
packer
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kristopher Ruzic
packer
Commits
0c0f8766
Commit
0c0f8766
authored
Jun 13, 2015
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
communicator/winrm
parent
acf31c31
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
305 additions
and
0 deletions
+305
-0
communicator/winrm/communicator.go
communicator/winrm/communicator.go
+129
-0
communicator/winrm/communicator_test.go
communicator/winrm/communicator_test.go
+94
-0
communicator/winrm/config.go
communicator/winrm/config.go
+14
-0
communicator/winrm/time.go
communicator/winrm/time.go
+32
-0
communicator/winrm/time_test.go
communicator/winrm/time_test.go
+36
-0
No files found.
communicator/winrm/communicator.go
0 → 100644
View file @
0c0f8766
package
winrm
import
(
"fmt"
"io"
"log"
"github.com/masterzen/winrm/winrm"
"github.com/mitchellh/packer/packer"
"github.com/packer-community/winrmcp/winrmcp"
// This import is a bit strange, but it's needed so `make updatedeps`
// can see and download it
_
"github.com/dylanmei/winrmtest"
)
// Communicator represents the WinRM communicator
type
Communicator
struct
{
config
*
Config
client
*
winrm
.
Client
endpoint
*
winrm
.
Endpoint
}
// New creates a new communicator implementation over WinRM.
func
New
(
config
*
Config
)
(
*
Communicator
,
error
)
{
endpoint
:=
&
winrm
.
Endpoint
{
Host
:
config
.
Host
,
Port
:
config
.
Port
,
/*
TODO
HTTPS: connInfo.HTTPS,
Insecure: connInfo.Insecure,
CACert: connInfo.CACert,
*/
}
// Create the client
params
:=
winrm
.
DefaultParameters
()
params
.
Timeout
=
formatDuration
(
config
.
Timeout
)
client
,
err
:=
winrm
.
NewClientWithParameters
(
endpoint
,
config
.
Username
,
config
.
Password
,
params
)
if
err
!=
nil
{
return
nil
,
err
}
// Create the shell to verify the connection
log
.
Printf
(
"[DEBUG] connecting to remote shell using WinRM"
)
shell
,
err
:=
client
.
CreateShell
()
if
err
!=
nil
{
log
.
Printf
(
"[ERROR] connection error: %s"
,
err
)
return
nil
,
err
}
if
err
:=
shell
.
Close
();
err
!=
nil
{
log
.
Printf
(
"[ERROR] error closing connection: %s"
,
err
)
return
nil
,
err
}
return
&
Communicator
{
config
:
config
,
client
:
client
,
endpoint
:
endpoint
,
},
nil
}
// Start implementation of communicator.Communicator interface
func
(
c
*
Communicator
)
Start
(
rc
*
packer
.
RemoteCmd
)
error
{
shell
,
err
:=
c
.
client
.
CreateShell
()
if
err
!=
nil
{
return
err
}
log
.
Printf
(
"[INFO] starting remote command: %s"
,
rc
.
Command
)
cmd
,
err
:=
shell
.
Execute
(
rc
.
Command
)
if
err
!=
nil
{
return
err
}
go
runCommand
(
shell
,
cmd
,
rc
)
return
nil
}
func
runCommand
(
shell
*
winrm
.
Shell
,
cmd
*
winrm
.
Command
,
rc
*
packer
.
RemoteCmd
)
{
defer
shell
.
Close
()
go
io
.
Copy
(
rc
.
Stdout
,
cmd
.
Stdout
)
go
io
.
Copy
(
rc
.
Stderr
,
cmd
.
Stderr
)
cmd
.
Wait
()
rc
.
SetExited
(
cmd
.
ExitCode
())
}
// Upload implementation of communicator.Communicator interface
func
(
c
*
Communicator
)
Upload
(
path
string
,
input
io
.
Reader
)
error
{
wcp
,
err
:=
c
.
newCopyClient
()
if
err
!=
nil
{
return
err
}
log
.
Printf
(
"Uploading file to '%s'"
,
path
)
return
wcp
.
Write
(
path
,
input
)
}
// UploadScript implementation of communicator.Communicator interface
func
(
c
*
Communicator
)
UploadScript
(
path
string
,
input
io
.
Reader
)
error
{
return
c
.
Upload
(
path
,
input
)
}
// UploadDir implementation of communicator.Communicator interface
func
(
c
*
Communicator
)
UploadDir
(
dst
string
,
src
string
)
error
{
log
.
Printf
(
"Uploading dir '%s' to '%s'"
,
src
,
dst
)
wcp
,
err
:=
c
.
newCopyClient
()
if
err
!=
nil
{
return
err
}
return
wcp
.
Copy
(
src
,
dst
)
}
func
(
c
*
Communicator
)
newCopyClient
()
(
*
winrmcp
.
Winrmcp
,
error
)
{
addr
:=
fmt
.
Sprintf
(
"%s:%d"
,
c
.
endpoint
.
Host
,
c
.
endpoint
.
Port
)
return
winrmcp
.
New
(
addr
,
&
winrmcp
.
Config
{
Auth
:
winrmcp
.
Auth
{
User
:
c
.
config
.
Username
,
Password
:
c
.
config
.
Password
,
},
OperationTimeout
:
c
.
config
.
Timeout
,
MaxOperationsPerShell
:
15
,
// lowest common denominator
})
}
communicator/winrm/communicator_test.go
0 → 100644
View file @
0c0f8766
package
winrm
import
(
"bytes"
"io"
"testing"
"time"
"github.com/dylanmei/winrmtest"
"github.com/mitchellh/packer/packer"
)
func
newMockWinRMServer
(
t
*
testing
.
T
)
*
winrmtest
.
Remote
{
wrm
:=
winrmtest
.
NewRemote
()
wrm
.
CommandFunc
(
winrmtest
.
MatchText
(
"echo foo"
),
func
(
out
,
err
io
.
Writer
)
int
{
out
.
Write
([]
byte
(
"foo"
))
return
0
})
wrm
.
CommandFunc
(
winrmtest
.
MatchPattern
(
`^echo c29tZXRoaW5n >> ".*"$`
),
func
(
out
,
err
io
.
Writer
)
int
{
return
0
})
wrm
.
CommandFunc
(
winrmtest
.
MatchPattern
(
`^powershell.exe -EncodedCommand .*$`
),
func
(
out
,
err
io
.
Writer
)
int
{
return
0
})
wrm
.
CommandFunc
(
winrmtest
.
MatchText
(
"powershell"
),
func
(
out
,
err
io
.
Writer
)
int
{
return
0
})
return
wrm
}
func
TestStart
(
t
*
testing
.
T
)
{
wrm
:=
newMockWinRMServer
(
t
)
defer
wrm
.
Close
()
c
,
err
:=
New
(
&
Config
{
Host
:
wrm
.
Host
,
Port
:
wrm
.
Port
,
Username
:
"user"
,
Password
:
"pass"
,
Timeout
:
30
*
time
.
Second
,
})
if
err
!=
nil
{
t
.
Fatalf
(
"error creating communicator: %s"
,
err
)
}
var
cmd
packer
.
RemoteCmd
stdout
:=
new
(
bytes
.
Buffer
)
cmd
.
Command
=
"echo foo"
cmd
.
Stdout
=
stdout
err
=
c
.
Start
(
&
cmd
)
if
err
!=
nil
{
t
.
Fatalf
(
"error executing remote command: %s"
,
err
)
}
cmd
.
Wait
()
if
stdout
.
String
()
!=
"foo"
{
t
.
Fatalf
(
"bad command response: expected %q, got %q"
,
"foo"
,
stdout
.
String
())
}
}
func
TestUpload
(
t
*
testing
.
T
)
{
wrm
:=
newMockWinRMServer
(
t
)
defer
wrm
.
Close
()
c
,
err
:=
New
(
&
Config
{
Host
:
wrm
.
Host
,
Port
:
wrm
.
Port
,
Username
:
"user"
,
Password
:
"pass"
,
Timeout
:
30
*
time
.
Second
,
})
if
err
!=
nil
{
t
.
Fatalf
(
"error creating communicator: %s"
,
err
)
}
err
=
c
.
Upload
(
"C:/Temp/terraform.cmd"
,
bytes
.
NewReader
([]
byte
(
"something"
)))
if
err
!=
nil
{
t
.
Fatalf
(
"error uploading file: %s"
,
err
)
}
}
communicator/winrm/config.go
0 → 100644
View file @
0c0f8766
package
winrm
import
(
"time"
)
// Config is used to configure the WinRM connection
type
Config
struct
{
Host
string
Port
int
Username
string
Password
string
Timeout
time
.
Duration
}
communicator/winrm/time.go
0 → 100644
View file @
0c0f8766
package
winrm
import
(
"fmt"
"time"
)
// formatDuration formats the given time.Duration into an ISO8601
// duration string.
func
formatDuration
(
duration
time
.
Duration
)
string
{
// We're not supporting negative durations
if
duration
.
Seconds
()
<=
0
{
return
"PT0S"
}
h
:=
int
(
duration
.
Hours
())
m
:=
int
(
duration
.
Minutes
())
-
(
h
*
60
)
s
:=
int
(
duration
.
Seconds
())
-
(
h
*
3600
+
m
*
60
)
res
:=
"PT"
if
h
>
0
{
res
=
fmt
.
Sprintf
(
"%s%dH"
,
res
,
h
)
}
if
m
>
0
{
res
=
fmt
.
Sprintf
(
"%s%dM"
,
res
,
m
)
}
if
s
>
0
{
res
=
fmt
.
Sprintf
(
"%s%dS"
,
res
,
s
)
}
return
res
}
communicator/winrm/time_test.go
0 → 100644
View file @
0c0f8766
package
winrm
import
(
"testing"
"time"
)
func
TestFormatDuration
(
t
*
testing
.
T
)
{
// Test complex duration with hours, minutes, seconds
d
:=
time
.
Duration
(
3701
)
*
time
.
Second
s
:=
formatDuration
(
d
)
if
s
!=
"PT1H1M41S"
{
t
.
Fatalf
(
"bad ISO 8601 duration string: %s"
,
s
)
}
// Test only minutes duration
d
=
time
.
Duration
(
20
)
*
time
.
Minute
s
=
formatDuration
(
d
)
if
s
!=
"PT20M"
{
t
.
Fatalf
(
"bad ISO 8601 duration string for 20M: %s"
,
s
)
}
// Test only seconds
d
=
time
.
Duration
(
1
)
*
time
.
Second
s
=
formatDuration
(
d
)
if
s
!=
"PT1S"
{
t
.
Fatalf
(
"bad ISO 8601 duration string for 1S: %s"
,
s
)
}
// Test negative duration (unsupported)
d
=
time
.
Duration
(
-
1
)
*
time
.
Second
s
=
formatDuration
(
d
)
if
s
!=
"PT0S"
{
t
.
Fatalf
(
"bad ISO 8601 duration string for negative: %s"
,
s
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment