Skip to content

Commit

Permalink
provisioner: new Puppet provisioner (#18851)
Browse files Browse the repository at this point in the history
* Basic Puppet provisioner

* (fixup) fix snake_case use in Bolt

* (fixup) Remove unused ValidateFunc

* (fixup) Check bolt result status

* (lint) go fmt

* Requested changes

* Remove PE autodetection

* Apply suggestions from @svanharmelen

Co-Authored-By: rodjek <[email protected]>

* Tag all JSON fields in bolt output

* Defer comm.Disconnect() as suggested

* Make bolt timeout configurable

* Update builtin/provisioners/puppet/resource_provisioner.go

Co-Authored-By: rodjek <[email protected]>

* Make extension_requests and custom_attributes configurable
  • Loading branch information
rodjek authored and mildwonkey committed Jun 10, 2019
1 parent 0abb0a0 commit 615110e
Show file tree
Hide file tree
Showing 9 changed files with 1,457 additions and 0 deletions.
12 changes: 12 additions & 0 deletions builtin/bins/provisioner-puppet/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"github.com/hashicorp/terraform/builtin/provisioners/puppet"
"github.com/hashicorp/terraform/plugin"
)

func main() {
plugin.Serve(&plugin.ServeOpts{
ProvisionerFunc: puppet.Provisioner,
})
}
74 changes: 74 additions & 0 deletions builtin/provisioners/puppet/bolt/bolt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package bolt

import (
"context"
"encoding/json"
"fmt"
"os/exec"
"runtime"
"strings"
"time"
)

type Result struct {
Items []struct {
Node string `json:"node"`
Status string `json:"status"`
Result map[string]string `json:"result"`
} `json:"items"`
NodeCount int `json:"node_count"`
ElapsedTime int `json:"elapsed_time"`
}

func runCommand(command string, timeout time.Duration) ([]byte, error) {
var cmdargs []string

if runtime.GOOS == "windows" {
cmdargs = []string{"cmd", "/C"}
} else {
cmdargs = []string{"/bin/sh", "-c"}
}
cmdargs = append(cmdargs, command)

ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

cmd := exec.CommandContext(ctx, cmdargs[0], cmdargs[1:]...)
return cmd.Output()
}

func Task(connInfo map[string]string, timeout time.Duration, sudo bool, task string, args map[string]string) (*Result, error) {
cmdargs := []string{
"bolt", "task", "run", "--nodes", connInfo["type"] + "://" + connInfo["host"], "-u", connInfo["user"],
}

if connInfo["type"] == "winrm" {
cmdargs = append(cmdargs, "-p", "\""+connInfo["password"]+"\"", "--no-ssl")
} else {
if sudo {
cmdargs = append(cmdargs, "--run-as", "root")
}

cmdargs = append(cmdargs, "--no-host-key-check")
}

cmdargs = append(cmdargs, "--format", "json", "--connect-timeout", "120", task)

if args != nil {
for key, value := range args {
cmdargs = append(cmdargs, strings.Join([]string{key, value}, "="))
}
}

out, err := runCommand(strings.Join(cmdargs, " "), timeout)
if err != nil {
return nil, fmt.Errorf("Bolt: \"%s\": %s: %s", strings.Join(cmdargs, " "), out, err)
}

result := new(Result)
if err = json.Unmarshal(out, result); err != nil {
return nil, err
}

return result, nil
}
65 changes: 65 additions & 0 deletions builtin/provisioners/puppet/linux_provisioner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package puppet

import (
"fmt"
"io"

"github.com/hashicorp/terraform/communicator/remote"
)

func (p *provisioner) linuxUploadFile(f io.Reader, dir string, filename string) error {
_, err := p.runCommand("mkdir -p " + dir)
if err != nil {
return fmt.Errorf("Failed to make directory %s: %s", dir, err)
}

err = p.comm.Upload("/tmp/"+filename, f)
if err != nil {
return fmt.Errorf("Failed to upload %s to /tmp: %s", filename, err)
}

_, err = p.runCommand(fmt.Sprintf("mv /tmp/%s %s/%s", filename, dir, filename))
return err
}

func (p *provisioner) linuxDefaultCertname() (string, error) {
certname, err := p.runCommand("hostname -f")
if err != nil {
return "", err
}

return certname, nil
}

func (p *provisioner) linuxInstallPuppetAgent() error {
_, err := p.runCommand(fmt.Sprintf("curl -kO https://%s:8140/packages/current/install.bash", p.Server))
if err != nil {
return err
}

_, err = p.runCommand("bash -- ./install.bash --puppet-service-ensure stopped")
if err != nil {
return err
}

_, err = p.runCommand("rm -f install.bash")
return err
}

func (p *provisioner) linuxRunPuppetAgent() error {
_, err := p.runCommand(fmt.Sprintf(
"/opt/puppetlabs/puppet/bin/puppet agent --test --server %s --environment %s",
p.Server,
p.Environment,
))

// Puppet exits 2 if changes have been successfully made.
if err != nil {
errStruct, _ := err.(*remote.ExitError)
if errStruct.ExitStatus == 2 {
return nil
}
}

return err
}
Loading

0 comments on commit 615110e

Please sign in to comment.