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
96b0ec53
Commit
96b0ec53
authored
Oct 27, 2014
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Start putting commands in command/, modify core
parent
4406c20a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
405 additions
and
17 deletions
+405
-17
command/build.go
command/build.go
+309
-0
command/meta.go
command/meta.go
+15
-0
commands.go
commands.go
+61
-0
config.go
config.go
+3
-0
packer.go
packer.go
+17
-17
No files found.
command/build.go
0 → 100644
View file @
96b0ec53
package
command
import
(
"bytes"
"flag"
"fmt"
cmdcommon
"github.com/mitchellh/packer/common/command"
"github.com/mitchellh/packer/packer"
"log"
"os"
"os/signal"
"strconv"
"strings"
"sync"
)
type
BuildCommand
struct
{
Meta
}
func
(
c
BuildCommand
)
Run
(
args
[]
string
)
int
{
var
cfgColor
,
cfgDebug
,
cfgForce
,
cfgParallel
bool
buildOptions
:=
new
(
cmdcommon
.
BuildOptions
)
env
,
err
:=
c
.
Meta
.
Environment
()
if
err
!=
nil
{
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error initializing environment: %s"
,
err
))
return
1
}
cmdFlags
:=
flag
.
NewFlagSet
(
"build"
,
flag
.
ContinueOnError
)
cmdFlags
.
Usage
=
func
()
{
env
.
Ui
()
.
Say
(
c
.
Help
())
}
cmdFlags
.
BoolVar
(
&
cfgColor
,
"color"
,
true
,
"enable or disable color"
)
cmdFlags
.
BoolVar
(
&
cfgDebug
,
"debug"
,
false
,
"debug mode for builds"
)
cmdFlags
.
BoolVar
(
&
cfgForce
,
"force"
,
false
,
"force a build if artifacts exist"
)
cmdFlags
.
BoolVar
(
&
cfgParallel
,
"parallel"
,
true
,
"enable/disable parallelization"
)
cmdcommon
.
BuildOptionFlags
(
cmdFlags
,
buildOptions
)
if
err
:=
cmdFlags
.
Parse
(
args
);
err
!=
nil
{
return
1
}
args
=
cmdFlags
.
Args
()
if
len
(
args
)
!=
1
{
cmdFlags
.
Usage
()
return
1
}
if
err
:=
buildOptions
.
Validate
();
err
!=
nil
{
env
.
Ui
()
.
Error
(
err
.
Error
())
env
.
Ui
()
.
Error
(
""
)
env
.
Ui
()
.
Error
(
c
.
Help
())
return
1
}
userVars
,
err
:=
buildOptions
.
AllUserVars
()
if
err
!=
nil
{
env
.
Ui
()
.
Error
(
fmt
.
Sprintf
(
"Error compiling user variables: %s"
,
err
))
env
.
Ui
()
.
Error
(
""
)
env
.
Ui
()
.
Error
(
c
.
Help
())
return
1
}
// Read the file into a byte array so that we can parse the template
log
.
Printf
(
"Reading template: %s"
,
args
[
0
])
tpl
,
err
:=
packer
.
ParseTemplateFile
(
args
[
0
],
userVars
)
if
err
!=
nil
{
env
.
Ui
()
.
Error
(
fmt
.
Sprintf
(
"Failed to parse template: %s"
,
err
))
return
1
}
// The component finder for our builds
components
:=
&
packer
.
ComponentFinder
{
Builder
:
env
.
Builder
,
Hook
:
env
.
Hook
,
PostProcessor
:
env
.
PostProcessor
,
Provisioner
:
env
.
Provisioner
,
}
// Go through each builder and compile the builds that we care about
builds
,
err
:=
buildOptions
.
Builds
(
tpl
,
components
)
if
err
!=
nil
{
env
.
Ui
()
.
Error
(
err
.
Error
())
return
1
}
if
cfgDebug
{
env
.
Ui
()
.
Say
(
"Debug mode enabled. Builds will not be parallelized."
)
}
// Compile all the UIs for the builds
colors
:=
[
5
]
packer
.
UiColor
{
packer
.
UiColorGreen
,
packer
.
UiColorCyan
,
packer
.
UiColorMagenta
,
packer
.
UiColorYellow
,
packer
.
UiColorBlue
,
}
buildUis
:=
make
(
map
[
string
]
packer
.
Ui
)
for
i
,
b
:=
range
builds
{
var
ui
packer
.
Ui
ui
=
env
.
Ui
()
if
cfgColor
{
ui
=
&
packer
.
ColoredUi
{
Color
:
colors
[
i
%
len
(
colors
)],
Ui
:
env
.
Ui
(),
}
}
buildUis
[
b
.
Name
()]
=
ui
ui
.
Say
(
fmt
.
Sprintf
(
"%s output will be in this color."
,
b
.
Name
()))
}
// Add a newline between the color output and the actual output
env
.
Ui
()
.
Say
(
""
)
log
.
Printf
(
"Build debug mode: %v"
,
cfgDebug
)
log
.
Printf
(
"Force build: %v"
,
cfgForce
)
// Set the debug and force mode and prepare all the builds
for
_
,
b
:=
range
builds
{
log
.
Printf
(
"Preparing build: %s"
,
b
.
Name
())
b
.
SetDebug
(
cfgDebug
)
b
.
SetForce
(
cfgForce
)
warnings
,
err
:=
b
.
Prepare
()
if
err
!=
nil
{
env
.
Ui
()
.
Error
(
err
.
Error
())
return
1
}
if
len
(
warnings
)
>
0
{
ui
:=
buildUis
[
b
.
Name
()]
ui
.
Say
(
fmt
.
Sprintf
(
"Warnings for build '%s':
\n
"
,
b
.
Name
()))
for
_
,
warning
:=
range
warnings
{
ui
.
Say
(
fmt
.
Sprintf
(
"* %s"
,
warning
))
}
ui
.
Say
(
""
)
}
}
// Run all the builds in parallel and wait for them to complete
var
interruptWg
,
wg
sync
.
WaitGroup
interrupted
:=
false
artifacts
:=
make
(
map
[
string
][]
packer
.
Artifact
)
errors
:=
make
(
map
[
string
]
error
)
for
_
,
b
:=
range
builds
{
// Increment the waitgroup so we wait for this item to finish properly
wg
.
Add
(
1
)
// Handle interrupts for this build
sigCh
:=
make
(
chan
os
.
Signal
,
1
)
signal
.
Notify
(
sigCh
,
os
.
Interrupt
)
defer
signal
.
Stop
(
sigCh
)
go
func
(
b
packer
.
Build
)
{
<-
sigCh
interruptWg
.
Add
(
1
)
defer
interruptWg
.
Done
()
interrupted
=
true
log
.
Printf
(
"Stopping build: %s"
,
b
.
Name
())
b
.
Cancel
()
log
.
Printf
(
"Build cancelled: %s"
,
b
.
Name
())
}(
b
)
// Run the build in a goroutine
go
func
(
b
packer
.
Build
)
{
defer
wg
.
Done
()
name
:=
b
.
Name
()
log
.
Printf
(
"Starting build run: %s"
,
name
)
ui
:=
buildUis
[
name
]
runArtifacts
,
err
:=
b
.
Run
(
ui
,
env
.
Cache
())
if
err
!=
nil
{
ui
.
Error
(
fmt
.
Sprintf
(
"Build '%s' errored: %s"
,
name
,
err
))
errors
[
name
]
=
err
}
else
{
ui
.
Say
(
fmt
.
Sprintf
(
"Build '%s' finished."
,
name
))
artifacts
[
name
]
=
runArtifacts
}
}(
b
)
if
cfgDebug
{
log
.
Printf
(
"Debug enabled, so waiting for build to finish: %s"
,
b
.
Name
())
wg
.
Wait
()
}
if
!
cfgParallel
{
log
.
Printf
(
"Parallelization disabled, waiting for build to finish: %s"
,
b
.
Name
())
wg
.
Wait
()
}
if
interrupted
{
log
.
Println
(
"Interrupted, not going to start any more builds."
)
break
}
}
// Wait for both the builds to complete and the interrupt handler,
// if it is interrupted.
log
.
Printf
(
"Waiting on builds to complete..."
)
wg
.
Wait
()
log
.
Printf
(
"Builds completed. Waiting on interrupt barrier..."
)
interruptWg
.
Wait
()
if
interrupted
{
env
.
Ui
()
.
Say
(
"Cleanly cancelled builds after being interrupted."
)
return
1
}
if
len
(
errors
)
>
0
{
env
.
Ui
()
.
Machine
(
"error-count"
,
strconv
.
FormatInt
(
int64
(
len
(
errors
)),
10
))
env
.
Ui
()
.
Error
(
"
\n
==> Some builds didn't complete successfully and had errors:"
)
for
name
,
err
:=
range
errors
{
// Create a UI for the machine readable stuff to be targetted
ui
:=
&
packer
.
TargettedUi
{
Target
:
name
,
Ui
:
env
.
Ui
(),
}
ui
.
Machine
(
"error"
,
err
.
Error
())
env
.
Ui
()
.
Error
(
fmt
.
Sprintf
(
"--> %s: %s"
,
name
,
err
))
}
}
if
len
(
artifacts
)
>
0
{
env
.
Ui
()
.
Say
(
"
\n
==> Builds finished. The artifacts of successful builds are:"
)
for
name
,
buildArtifacts
:=
range
artifacts
{
// Create a UI for the machine readable stuff to be targetted
ui
:=
&
packer
.
TargettedUi
{
Target
:
name
,
Ui
:
env
.
Ui
(),
}
// Machine-readable helpful
ui
.
Machine
(
"artifact-count"
,
strconv
.
FormatInt
(
int64
(
len
(
buildArtifacts
)),
10
))
for
i
,
artifact
:=
range
buildArtifacts
{
var
message
bytes
.
Buffer
fmt
.
Fprintf
(
&
message
,
"--> %s: "
,
name
)
if
artifact
!=
nil
{
fmt
.
Fprintf
(
&
message
,
artifact
.
String
())
}
else
{
fmt
.
Fprint
(
&
message
,
"<nothing>"
)
}
iStr
:=
strconv
.
FormatInt
(
int64
(
i
),
10
)
if
artifact
!=
nil
{
ui
.
Machine
(
"artifact"
,
iStr
,
"builder-id"
,
artifact
.
BuilderId
())
ui
.
Machine
(
"artifact"
,
iStr
,
"id"
,
artifact
.
Id
())
ui
.
Machine
(
"artifact"
,
iStr
,
"string"
,
artifact
.
String
())
files
:=
artifact
.
Files
()
ui
.
Machine
(
"artifact"
,
iStr
,
"files-count"
,
strconv
.
FormatInt
(
int64
(
len
(
files
)),
10
))
for
fi
,
file
:=
range
files
{
fiStr
:=
strconv
.
FormatInt
(
int64
(
fi
),
10
)
ui
.
Machine
(
"artifact"
,
iStr
,
"file"
,
fiStr
,
file
)
}
}
else
{
ui
.
Machine
(
"artifact"
,
iStr
,
"nil"
)
}
ui
.
Machine
(
"artifact"
,
iStr
,
"end"
)
env
.
Ui
()
.
Say
(
message
.
String
())
}
}
}
else
{
env
.
Ui
()
.
Say
(
"
\n
==> Builds finished but no artifacts were created."
)
}
if
len
(
errors
)
>
0
{
// If any errors occurred, exit with a non-zero exit status
return
1
}
return
0
}
func
(
BuildCommand
)
Help
()
string
{
helpText
:=
`
Usage: packer build [options] TEMPLATE
Will execute multiple builds in parallel as defined in the template.
The various artifacts created by the template will be outputted.
Options:
-debug Debug mode enabled for builds
-force Force a build to continue if artifacts exist, deletes existing artifacts
-machine-readable Machine-readable output
-except=foo,bar,baz Build all builds other than these
-only=foo,bar,baz Only build the given builds by name
-parallel=false Disable parallelization (on by default)
-var 'key=value' Variable for templates, can be used multiple times.
-var-file=path JSON file containing user variables.
`
return
strings
.
TrimSpace
(
helpText
)
}
func
(
BuildCommand
)
Synopsis
()
string
{
return
"build image(s) from template"
}
command/meta.go
0 → 100644
View file @
96b0ec53
package
command
import
(
"github.com/mitchellh/cli"
"github.com/mitchellh/packer/packer"
)
type
Meta
struct
{
EnvConfig
*
packer
.
EnvironmentConfig
Ui
cli
.
Ui
}
func
(
m
*
Meta
)
Environment
()
(
packer
.
Environment
,
error
)
{
return
packer
.
NewEnvironment
(
m
.
EnvConfig
)
}
commands.go
0 → 100644
View file @
96b0ec53
package
main
import
(
"os"
"os/signal"
"github.com/mitchellh/cli"
"github.com/mitchellh/packer/command"
)
// Commands is the mapping of all the available Terraform commands.
var
Commands
map
[
string
]
cli
.
CommandFactory
// Ui is the cli.Ui used for communicating to the outside world.
var
Ui
cli
.
Ui
const
ErrorPrefix
=
"e:"
const
OutputPrefix
=
"o:"
func
init
()
{
Ui
=
&
cli
.
BasicUi
{
Writer
:
os
.
Stdout
}
/*
Ui = &cli.PrefixedUi{
AskPrefix: OutputPrefix,
OutputPrefix: OutputPrefix,
InfoPrefix: OutputPrefix,
ErrorPrefix: ErrorPrefix,
Ui: &cli.BasicUi{Writer: os.Stdout},
}
*/
meta
:=
command
.
Meta
{
EnvConfig
:
&
EnvConfig
,
Ui
:
Ui
,
}
Commands
=
map
[
string
]
cli
.
CommandFactory
{
"build"
:
func
()
(
cli
.
Command
,
error
)
{
return
&
command
.
BuildCommand
{
Meta
:
meta
,
},
nil
},
}
}
// makeShutdownCh creates an interrupt listener and returns a channel.
// A message will be sent on the channel for every interrupt received.
func
makeShutdownCh
()
<-
chan
struct
{}
{
resultCh
:=
make
(
chan
struct
{})
signalCh
:=
make
(
chan
os
.
Signal
,
4
)
signal
.
Notify
(
signalCh
,
os
.
Interrupt
)
go
func
()
{
for
{
<-
signalCh
resultCh
<-
struct
{}{}
}
}()
return
resultCh
}
config.go
View file @
96b0ec53
...
...
@@ -13,6 +13,9 @@ import (
"github.com/mitchellh/packer/packer/plugin"
)
// EnvConfig is the global EnvironmentConfig we use to initialize the CLI.
var
EnvConfig
packer
.
EnvironmentConfig
type
config
struct
{
DisableCheckpoint
bool
`json:"disable_checkpoint"`
DisableCheckpointSignature
bool
`json:"disable_checkpoint_signature"`
...
...
packer.go
View file @
96b0ec53
...
...
@@ -10,6 +10,7 @@ import (
"path/filepath"
"runtime"
"github.com/mitchellh/cli"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/packer/plugin"
"github.com/mitchellh/panicwrap"
...
...
@@ -118,16 +119,14 @@ func wrappedMain() int {
defer
plugin
.
CleanupClients
()
// Create the environment configuration
envConfig
:=
packer
.
DefaultEnvironmentConfig
()
envConfig
.
Cache
=
cache
envConfig
.
Commands
=
config
.
CommandNames
()
envConfig
.
Components
.
Builder
=
config
.
LoadBuilder
envConfig
.
Components
.
Command
=
config
.
LoadCommand
envConfig
.
Components
.
Hook
=
config
.
LoadHook
envConfig
.
Components
.
PostProcessor
=
config
.
LoadPostProcessor
envConfig
.
Components
.
Provisioner
=
config
.
LoadProvisioner
EnvConfig
=
*
packer
.
DefaultEnvironmentConfig
()
EnvConfig
.
Cache
=
cache
EnvConfig
.
Components
.
Builder
=
config
.
LoadBuilder
EnvConfig
.
Components
.
Hook
=
config
.
LoadHook
EnvConfig
.
Components
.
PostProcessor
=
config
.
LoadPostProcessor
EnvConfig
.
Components
.
Provisioner
=
config
.
LoadProvisioner
if
machineReadable
{
e
nvConfig
.
Ui
=
&
packer
.
MachineReadableUi
{
E
nvConfig
.
Ui
=
&
packer
.
MachineReadableUi
{
Writer
:
os
.
Stdout
,
}
...
...
@@ -139,17 +138,18 @@ func wrappedMain() int {
}
}
env
,
err
:=
packer
.
NewEnvironment
(
envConfig
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Packer initialization error:
\n\n
%s
\n
"
,
err
)
return
1
}
//setupSignalHandlers(env)
setupSignalHandlers
(
env
)
cli
:=
&
cli
.
CLI
{
Args
:
args
,
Commands
:
Commands
,
HelpFunc
:
cli
.
BasicHelpFunc
(
"packer"
),
HelpWriter
:
os
.
Stdout
,
}
exitCode
,
err
:=
env
.
Cli
(
args
)
exitCode
,
err
:=
cli
.
Run
(
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Error executing CLI: %s
\n
"
,
err
.
Error
()
)
fmt
.
Fprintf
(
os
.
Stderr
,
"Error executing CLI: %s
\n
"
,
err
)
return
1
}
...
...
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