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
80fc1f03
Commit
80fc1f03
authored
Jun 19, 2015
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
provisioner/shell-local: a first stab
parent
f41429b6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
257 additions
and
0 deletions
+257
-0
provisioner/shell-local/communicator.go
provisioner/shell-local/communicator.go
+81
-0
provisioner/shell-local/provisioner.go
provisioner/shell-local/provisioner.go
+109
-0
provisioner/shell-local/provisioner_test.go
provisioner/shell-local/provisioner_test.go
+67
-0
No files found.
provisioner/shell-local/communicator.go
0 → 100644
View file @
80fc1f03
package
shell
import
(
"fmt"
"io"
"os"
"os/exec"
"syscall"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type
Communicator
struct
{
ExecuteCommand
[]
string
Ctx
interpolate
.
Context
}
func
(
c
*
Communicator
)
Start
(
cmd
*
packer
.
RemoteCmd
)
error
{
// Render the template so that we know how to execute the command
c
.
Ctx
.
Data
=
&
ExecuteCommandTemplate
{
Command
:
cmd
.
Command
,
}
for
i
,
field
:=
range
c
.
ExecuteCommand
{
command
,
err
:=
interpolate
.
Render
(
field
,
&
c
.
Ctx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error processing command: %s"
,
err
)
}
c
.
ExecuteCommand
[
i
]
=
command
}
// Build the local command to execute
localCmd
:=
exec
.
Command
(
c
.
ExecuteCommand
[
0
],
c
.
ExecuteCommand
[
1
:
]
...
)
localCmd
.
Stdin
=
cmd
.
Stdin
localCmd
.
Stdout
=
cmd
.
Stdout
localCmd
.
Stderr
=
cmd
.
Stderr
// Start it. If it doesn't work, then error right away.
if
err
:=
localCmd
.
Start
();
err
!=
nil
{
return
err
}
// We've started successfully. Start a goroutine to wait for
// it to complete and track exit status.
go
func
()
{
var
exitStatus
int
err
:=
localCmd
.
Wait
()
if
err
!=
nil
{
if
exitErr
,
ok
:=
err
.
(
*
exec
.
ExitError
);
ok
{
exitStatus
=
1
// There is no process-independent way to get the REAL
// exit status so we just try to go deeper.
if
status
,
ok
:=
exitErr
.
Sys
()
.
(
syscall
.
WaitStatus
);
ok
{
exitStatus
=
status
.
ExitStatus
()
}
}
}
cmd
.
SetExited
(
exitStatus
)
}()
return
nil
}
func
(
c
*
Communicator
)
Upload
(
string
,
io
.
Reader
,
*
os
.
FileInfo
)
error
{
return
fmt
.
Errorf
(
"upload not supported"
)
}
func
(
c
*
Communicator
)
UploadDir
(
string
,
string
,
[]
string
)
error
{
return
fmt
.
Errorf
(
"uploadDir not supported"
)
}
func
(
c
*
Communicator
)
Download
(
string
,
io
.
Writer
)
error
{
return
fmt
.
Errorf
(
"download not supported"
)
}
type
ExecuteCommandTemplate
struct
{
Command
string
}
provisioner/shell-local/provisioner.go
0 → 100644
View file @
80fc1f03
package
shell
import
(
"errors"
"fmt"
"runtime"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type
Config
struct
{
common
.
PackerConfig
`mapstructure:",squash"`
// Command is the command to execute
Command
string
// ExecuteCommand is the command used to execute the command.
ExecuteCommand
[]
string
`mapstructure:"execute_command"`
ctx
interpolate
.
Context
}
type
Provisioner
struct
{
config
Config
}
func
(
p
*
Provisioner
)
Prepare
(
raws
...
interface
{})
error
{
err
:=
config
.
Decode
(
&
p
.
config
,
&
config
.
DecodeOpts
{
Interpolate
:
true
,
InterpolateFilter
:
&
interpolate
.
RenderFilter
{
Exclude
:
[]
string
{
"execute_command"
,
},
},
},
raws
...
)
if
err
!=
nil
{
return
err
}
if
len
(
p
.
config
.
ExecuteCommand
)
==
0
{
if
runtime
.
GOOS
==
"windows"
{
p
.
config
.
ExecuteCommand
=
[]
string
{
"cmd"
,
"/C"
,
"{{.Command}}"
,
}
}
else
{
p
.
config
.
ExecuteCommand
=
[]
string
{
"/bin/sh"
,
"-c"
,
"{{.Command}}"
,
}
}
}
var
errs
*
packer
.
MultiError
if
p
.
config
.
Command
==
""
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
errors
.
New
(
"command must be specified"
))
}
if
len
(
p
.
config
.
ExecuteCommand
)
==
0
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
errors
.
New
(
"execute_command must not be empty"
))
}
if
errs
!=
nil
&&
len
(
errs
.
Errors
)
>
0
{
return
errs
}
return
nil
}
func
(
p
*
Provisioner
)
Provision
(
ui
packer
.
Ui
,
_
packer
.
Communicator
)
error
{
// Make another communicator for local
comm
:=
&
Communicator
{
Ctx
:
p
.
config
.
ctx
,
ExecuteCommand
:
p
.
config
.
ExecuteCommand
,
}
// Build the remote command
cmd
:=
&
packer
.
RemoteCmd
{
Command
:
p
.
config
.
Command
}
ui
.
Say
(
fmt
.
Sprintf
(
"Executing local command: %s"
,
p
.
config
.
Command
))
if
err
:=
cmd
.
StartWithUi
(
comm
,
ui
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Error executing command: %s
\n\n
"
+
"Please see output above for more information."
,
p
.
config
.
Command
)
}
if
cmd
.
ExitStatus
!=
0
{
return
fmt
.
Errorf
(
"Erroneous exit code %s while executing command: %s
\n\n
"
+
"Please see output above for more information."
,
cmd
.
ExitStatus
,
p
.
config
.
Command
)
}
return
nil
}
func
(
p
*
Provisioner
)
Cancel
()
{
// Just do nothing. When the process ends, so will our provisioner
}
provisioner/shell-local/provisioner_test.go
0 → 100644
View file @
80fc1f03
package
shell
import
(
"testing"
"github.com/mitchellh/packer/packer"
)
func
TestProvisioner_impl
(
t
*
testing
.
T
)
{
var
_
packer
.
Provisioner
=
new
(
Provisioner
)
}
func
TestConfigPrepare
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
Key
string
Value
interface
{}
Err
bool
}{
{
"unknown_key"
,
"bad"
,
true
,
},
{
"command"
,
nil
,
true
,
},
}
for
_
,
tc
:=
range
cases
{
raw
:=
testConfig
(
t
)
if
tc
.
Value
==
nil
{
delete
(
raw
,
tc
.
Key
)
}
else
{
raw
[
tc
.
Key
]
=
tc
.
Value
}
var
p
Provisioner
err
:=
p
.
Prepare
(
raw
)
if
tc
.
Err
{
testConfigErr
(
t
,
err
,
tc
.
Key
)
}
else
{
testConfigOk
(
t
,
err
)
}
}
}
func
testConfig
(
t
*
testing
.
T
)
map
[
string
]
interface
{}
{
return
map
[
string
]
interface
{}{
"command"
:
"echo foo"
,
}
}
func
testConfigErr
(
t
*
testing
.
T
,
err
error
,
extra
string
)
{
if
err
==
nil
{
t
.
Fatalf
(
"should error: %s"
,
extra
)
}
}
func
testConfigOk
(
t
*
testing
.
T
,
err
error
)
{
if
err
!=
nil
{
t
.
Fatalf
(
"bad: %s"
,
err
)
}
}
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