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
2af91add
Commit
2af91add
authored
Feb 24, 2014
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #796 from Jimdo/puppet-server
Add puppet server provisioner
parents
000e5b67
ee506570
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
440 additions
and
1 deletion
+440
-1
config.go
config.go
+1
-0
plugin/provisioner-puppet-server/main.go
plugin/provisioner-puppet-server/main.go
+15
-0
plugin/provisioner-puppet-server/main_test.go
plugin/provisioner-puppet-server/main_test.go
+1
-0
provisioner/puppet-server/provisioner.go
provisioner/puppet-server/provisioner.go
+256
-0
provisioner/puppet-server/provisioner_test.go
provisioner/puppet-server/provisioner_test.go
+93
-0
website/source/docs/provisioners/puppet-server.html.markdown
website/source/docs/provisioners/puppet-server.html.markdown
+72
-0
website/source/layouts/docs.erb
website/source/layouts/docs.erb
+2
-1
No files found.
config.go
View file @
2af91add
...
...
@@ -53,6 +53,7 @@ const defaultConfig = `
"chef-solo": "packer-provisioner-chef-solo",
"file": "packer-provisioner-file",
"puppet-masterless": "packer-provisioner-puppet-masterless",
"puppet-server": "packer-provisioner-puppet-server",
"shell": "packer-provisioner-shell",
"salt-masterless": "packer-provisioner-salt-masterless"
}
...
...
plugin/provisioner-puppet-server/main.go
0 → 100644
View file @
2af91add
package
main
import
(
"github.com/mitchellh/packer/packer/plugin"
"github.com/mitchellh/packer/provisioner/puppet-server"
)
func
main
()
{
server
,
err
:=
plugin
.
Server
()
if
err
!=
nil
{
panic
(
err
)
}
server
.
RegisterProvisioner
(
new
(
puppetserver
.
Provisioner
))
server
.
Serve
()
}
plugin/provisioner-puppet-server/main_test.go
0 → 100644
View file @
2af91add
package
main
provisioner/puppet-server/provisioner.go
0 → 100644
View file @
2af91add
// This package implements a provisioner for Packer that executes
// Puppet on the remote machine connecting to a Puppet master.
package
puppetserver
import
(
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os"
"strings"
)
type
Config
struct
{
common
.
PackerConfig
`mapstructure:",squash"`
tpl
*
packer
.
ConfigTemplate
// Additional facts to set when executing Puppet
Facter
map
[
string
]
string
// A path to the client certificate
ClientCertPath
string
`mapstructure:"client_cert_path"`
// A path to a directory containing the client private keys
ClientPrivateKeyPath
string
`mapstructure:"client_private_key_path"`
// The hostname of the Puppet node.
PuppetNode
string
`mapstructure:"puppet_node"`
// The hostname of the Puppet server.
PuppetServer
string
`mapstructure:"puppet_server"`
// Additional options to be passed to `puppet agent`.
Options
string
`mapstructure:"options"`
// If true, `sudo` will NOT be used to execute Puppet.
PreventSudo
bool
`mapstructure:"prevent_sudo"`
// The directory where files will be uploaded. Packer requires write
// permissions in this directory.
StagingDir
string
`mapstructure:"staging_dir"`
}
type
Provisioner
struct
{
config
Config
}
type
ExecuteTemplate
struct
{
FacterVars
string
ClientCertPath
string
ClientPrivateKeyPath
string
PuppetNode
string
PuppetServer
string
Options
string
Sudo
bool
}
func
(
p
*
Provisioner
)
Prepare
(
raws
...
interface
{})
error
{
md
,
err
:=
common
.
DecodeConfig
(
&
p
.
config
,
raws
...
)
if
err
!=
nil
{
return
err
}
p
.
config
.
tpl
,
err
=
packer
.
NewConfigTemplate
()
if
err
!=
nil
{
return
err
}
p
.
config
.
tpl
.
UserVars
=
p
.
config
.
PackerUserVars
// Accumulate any errors
errs
:=
common
.
CheckUnusedConfig
(
md
)
if
p
.
config
.
StagingDir
==
""
{
p
.
config
.
StagingDir
=
"/tmp/packer-puppet-server"
}
// Templates
templates
:=
map
[
string
]
*
string
{
"client_cert_dir"
:
&
p
.
config
.
ClientCertPath
,
"client_private_key_dir"
:
&
p
.
config
.
ClientPrivateKeyPath
,
"puppet_server"
:
&
p
.
config
.
PuppetServer
,
"puppet_node"
:
&
p
.
config
.
PuppetNode
,
"options"
:
&
p
.
config
.
Options
,
}
for
n
,
ptr
:=
range
templates
{
var
err
error
*
ptr
,
err
=
p
.
config
.
tpl
.
Process
(
*
ptr
,
nil
)
if
err
!=
nil
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"Error processing %s: %s"
,
n
,
err
))
}
}
newFacts
:=
make
(
map
[
string
]
string
)
for
k
,
v
:=
range
p
.
config
.
Facter
{
k
,
err
:=
p
.
config
.
tpl
.
Process
(
k
,
nil
)
if
err
!=
nil
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"Error processing facter key %s: %s"
,
k
,
err
))
continue
}
v
,
err
:=
p
.
config
.
tpl
.
Process
(
v
,
nil
)
if
err
!=
nil
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"Error processing facter value '%s': %s"
,
v
,
err
))
continue
}
newFacts
[
k
]
=
v
}
p
.
config
.
Facter
=
newFacts
if
p
.
config
.
ClientCertPath
!=
""
{
info
,
err
:=
os
.
Stat
(
p
.
config
.
ClientCertPath
)
if
err
!=
nil
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"client_cert_dir is invalid: %s"
,
err
))
}
else
if
!
info
.
IsDir
()
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"client_cert_dir must point to a directory"
))
}
}
if
p
.
config
.
ClientPrivateKeyPath
!=
""
{
info
,
err
:=
os
.
Stat
(
p
.
config
.
ClientPrivateKeyPath
)
if
err
!=
nil
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"client_private_key_dir is invalid: %s"
,
err
))
}
else
if
!
info
.
IsDir
()
{
errs
=
packer
.
MultiErrorAppend
(
errs
,
fmt
.
Errorf
(
"client_private_key_dir must point to a directory"
))
}
}
if
errs
!=
nil
&&
len
(
errs
.
Errors
)
>
0
{
return
errs
}
return
nil
}
func
(
p
*
Provisioner
)
Provision
(
ui
packer
.
Ui
,
comm
packer
.
Communicator
)
error
{
ui
.
Say
(
"Provisioning with Puppet..."
)
ui
.
Message
(
"Creating Puppet staging directory..."
)
if
err
:=
p
.
createDir
(
ui
,
comm
,
p
.
config
.
StagingDir
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Error creating staging directory: %s"
,
err
)
}
// Upload client cert dir if set
remoteClientCertPath
:=
""
if
p
.
config
.
ClientCertPath
!=
""
{
ui
.
Message
(
fmt
.
Sprintf
(
"Uploading client cert from: %s"
,
p
.
config
.
ClientCertPath
))
remoteClientCertPath
=
fmt
.
Sprintf
(
"%s/certs"
,
p
.
config
.
StagingDir
)
err
:=
p
.
uploadDirectory
(
ui
,
comm
,
remoteClientCertPath
,
p
.
config
.
ClientCertPath
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error uploading client cert: %s"
,
err
)
}
}
// Upload client cert dir if set
remoteClientPrivateKeyPath
:=
""
if
p
.
config
.
ClientPrivateKeyPath
!=
""
{
ui
.
Message
(
fmt
.
Sprintf
(
"Uploading client private keys from: %s"
,
p
.
config
.
ClientPrivateKeyPath
))
remoteClientPrivateKeyPath
=
fmt
.
Sprintf
(
"%s/private_keys"
,
p
.
config
.
StagingDir
)
err
:=
p
.
uploadDirectory
(
ui
,
comm
,
remoteClientPrivateKeyPath
,
p
.
config
.
ClientPrivateKeyPath
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Error uploading client private keys: %s"
,
err
)
}
}
// Compile the facter variables
facterVars
:=
make
([]
string
,
0
,
len
(
p
.
config
.
Facter
))
for
k
,
v
:=
range
p
.
config
.
Facter
{
facterVars
=
append
(
facterVars
,
fmt
.
Sprintf
(
"FACTER_%s='%s'"
,
k
,
v
))
}
// Execute Puppet
command
,
err
:=
p
.
config
.
tpl
.
Process
(
p
.
commandTemplate
(),
&
ExecuteTemplate
{
FacterVars
:
strings
.
Join
(
facterVars
,
" "
),
ClientCertPath
:
remoteClientCertPath
,
ClientPrivateKeyPath
:
remoteClientPrivateKeyPath
,
PuppetNode
:
p
.
config
.
PuppetNode
,
PuppetServer
:
p
.
config
.
PuppetServer
,
Options
:
p
.
config
.
Options
,
Sudo
:
!
p
.
config
.
PreventSudo
,
})
if
err
!=
nil
{
return
err
}
cmd
:=
&
packer
.
RemoteCmd
{
Command
:
command
,
}
ui
.
Message
(
fmt
.
Sprintf
(
"Running Puppet: %s"
,
command
))
if
err
:=
cmd
.
StartWithUi
(
comm
,
ui
);
err
!=
nil
{
return
err
}
if
cmd
.
ExitStatus
!=
0
&&
cmd
.
ExitStatus
!=
2
{
return
fmt
.
Errorf
(
"Puppet exited with a non-zero exit status: %d"
,
cmd
.
ExitStatus
)
}
return
nil
}
func
(
p
*
Provisioner
)
Cancel
()
{
// Just hard quit. It isn't a big deal if what we're doing keeps
// running on the other side.
os
.
Exit
(
0
)
}
func
(
p
*
Provisioner
)
createDir
(
ui
packer
.
Ui
,
comm
packer
.
Communicator
,
dir
string
)
error
{
cmd
:=
&
packer
.
RemoteCmd
{
Command
:
fmt
.
Sprintf
(
"mkdir -p '%s'"
,
dir
),
}
if
err
:=
cmd
.
StartWithUi
(
comm
,
ui
);
err
!=
nil
{
return
err
}
if
cmd
.
ExitStatus
!=
0
{
return
fmt
.
Errorf
(
"Non-zero exit status."
)
}
return
nil
}
func
(
p
*
Provisioner
)
uploadDirectory
(
ui
packer
.
Ui
,
comm
packer
.
Communicator
,
dst
string
,
src
string
)
error
{
if
err
:=
p
.
createDir
(
ui
,
comm
,
dst
);
err
!=
nil
{
return
err
}
// Make sure there is a trailing "/" so that the directory isn't
// created on the other side.
if
src
[
len
(
src
)
-
1
]
!=
'/'
{
src
=
src
+
"/"
}
return
comm
.
UploadDir
(
dst
,
src
,
nil
)
}
func
(
p
*
Provisioner
)
commandTemplate
()
string
{
return
"{{.FacterVars}} {{if .Sudo}} sudo -E {{end}}"
+
"puppet agent --onetime --no-daemonize "
+
"{{if ne .PuppetServer
\"\"
}}--server='{{.PuppetServer}}' {{end}}"
+
"{{if ne .Options
\"\"
}}{{.Options}} {{end}}"
+
"{{if ne .PuppetNode
\"\"
}}--certname={{.PuppetNode}} {{end}}"
+
"{{if ne .ClientCertPath
\"\"
}}--certdir='{{.ClientCertPath}}' {{end}}"
+
"{{if ne .ClientPrivateKeyPath
\"\"
}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}"
+
"--detailed-exitcodes"
}
provisioner/puppet-server/provisioner_test.go
0 → 100644
View file @
2af91add
package
puppetserver
import
(
"github.com/mitchellh/packer/packer"
"io/ioutil"
"os"
"testing"
)
func
testConfig
()
map
[
string
]
interface
{}
{
tf
,
err
:=
ioutil
.
TempFile
(
""
,
"packer"
)
if
err
!=
nil
{
panic
(
err
)
}
return
map
[
string
]
interface
{}{
"puppet_server"
:
tf
.
Name
(),
}
}
func
TestProvisioner_Impl
(
t
*
testing
.
T
)
{
var
raw
interface
{}
raw
=
&
Provisioner
{}
if
_
,
ok
:=
raw
.
(
packer
.
Provisioner
);
!
ok
{
t
.
Fatalf
(
"must be a Provisioner"
)
}
}
func
TestProvisionerPrepare_clientPrivateKeyPath
(
t
*
testing
.
T
)
{
config
:=
testConfig
()
delete
(
config
,
"client_private_key_path"
)
p
:=
new
(
Provisioner
)
err
:=
p
.
Prepare
(
config
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %s"
,
err
)
}
// Test with bad paths
config
[
"client_private_key_path"
]
=
"i-should-not-exist"
p
=
new
(
Provisioner
)
err
=
p
.
Prepare
(
config
)
if
err
==
nil
{
t
.
Fatal
(
"should be an error"
)
}
// Test with a good one
td
,
err
:=
ioutil
.
TempDir
(
""
,
"packer"
)
if
err
!=
nil
{
t
.
Fatalf
(
"error: %s"
,
err
)
}
defer
os
.
RemoveAll
(
td
)
config
[
"client_private_key_path"
]
=
td
p
=
new
(
Provisioner
)
err
=
p
.
Prepare
(
config
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %s"
,
err
)
}
}
func
TestProvisionerPrepare_clientCertPath
(
t
*
testing
.
T
)
{
config
:=
testConfig
()
delete
(
config
,
"client_cert_path"
)
p
:=
new
(
Provisioner
)
err
:=
p
.
Prepare
(
config
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %s"
,
err
)
}
// Test with bad paths
config
[
"client_cert_path"
]
=
"i-should-not-exist"
p
=
new
(
Provisioner
)
err
=
p
.
Prepare
(
config
)
if
err
==
nil
{
t
.
Fatal
(
"should be an error"
)
}
// Test with a good one
td
,
err
:=
ioutil
.
TempDir
(
""
,
"packer"
)
if
err
!=
nil
{
t
.
Fatalf
(
"error: %s"
,
err
)
}
defer
os
.
RemoveAll
(
td
)
config
[
"client_cert_path"
]
=
td
p
=
new
(
Provisioner
)
err
=
p
.
Prepare
(
config
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %s"
,
err
)
}
}
website/source/docs/provisioners/puppet-server.html.markdown
0 → 100644
View file @
2af91add
---
layout
:
"
docs"
page_title
:
"
Puppet
Server
Provisioner"
---
# Puppet Server Provisioner
Type:
`puppet-server`
The Puppet provisioner configures Puppet to run on the machines
communicating with a Puppet master.
<div
class=
"alert alert-info alert-block"
>
<strong>
Note that Puppet will
<em>
not
</em>
be installed automatically
by this provisioner.
</strong>
This provisioner expects that Puppet is already
installed on the machine. It is common practice to use the
<a
href=
"/docs/provisioners/shell.html"
>
shell provisioner
</a>
before the
Puppet provisioner to do this.
</div>
## Basic Example
The example below is fully functional and expects a Puppet server to be accessible
from your network.:
<pre
class=
"prettyprint"
>
{
"type": "puppet-server",
"options": "--test --pluginsync",
"facter": {
"server_role": "webserver"
}
}
</pre>
## Configuration Reference
The reference of available configuration options is listed below.
The provisioner takes various options. None are strictly
required. They are listed below:
*
`client_cert_path`
(string) - Path to the client certificate for the
node on your disk. This defaults to nothing, in which case a client
cert won't be uploaded.
*
`client_private_key_path`
(string) - Path to the client private key for
the node on your disk. This defaults to nothing, in which case a client
private key won't be uploaded.
*
`facter`
(hash) - Additional Facter facts to make available to the
Puppet run.
*
`options`
(string) - Additional command line options to pass
to
`puppet agent`
when Puppet is ran.
*
`puppet_node`
(string) - The name of the node. If this isn't set,
the fully qualified domain name will be used.
*
`puppet_server`
(string) - Hostname of the Puppet server. By default
"puppet" will be used.
*
`prevent_sudo`
(boolean) - By default, the configured commands that are
executed to run Puppet are executed with
`sudo`
. If this is true,
then the sudo will be omitted.
*
`staging_directory`
(string) - This is the directory where all the configuration
of Puppet by Packer will be placed. By default this is "/tmp/packer-puppet-server".
This directory doesn't need to exist but must have proper permissions so that
the SSH user that Packer uses is able to create directories and write into
this folder. If the permissions are not correct, use a shell provisioner
prior to this to configure it properly.
website/source/layouts/docs.erb
View file @
2af91add
...
...
@@ -48,7 +48,8 @@
<li><a
href=
"/docs/provisioners/ansible-local.html"
>
Ansible
</a></li>
<li><a
href=
"/docs/provisioners/chef-client.html"
>
Chef Client
</a></li>
<li><a
href=
"/docs/provisioners/chef-solo.html"
>
Chef Solo
</a></li>
<li><a
href=
"/docs/provisioners/puppet-masterless.html"
>
Puppet
</a></li>
<li><a
href=
"/docs/provisioners/puppet-masterless.html"
>
Puppet Masterless
</a></li>
<li><a
href=
"/docs/provisioners/puppet-server.html"
>
Puppet Server
</a></li>
<li><a
href=
"/docs/provisioners/salt-masterless.html"
>
Salt
</a></li>
<li><a
href=
"/docs/provisioners/custom.html"
>
Custom
</a></li>
</ul>
...
...
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