Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic Puppet provisioner #18851

Merged
merged 13 commits into from
Jun 10, 2019
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,
})
}
72 changes: 72 additions & 0 deletions builtin/provisioners/puppet/bolt/bolt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package bolt

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

type Result struct {
Items []struct {
Node string
Status string
Result map[string]string
}
NodeCount int `json:"node_count"`
ElapsedTime int `json:"elapsed_time"`
rodjek marked this conversation as resolved.
Show resolved Hide resolved
}

func runCommand(command string) ([]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(), 300*time.Second)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share the reasoning for adding this particular (hardcoded) timeout?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a safety precaution in case bolt hangs for some reason. I've changed the timeout to be configurable with a default value of 5 minutes.

defer cancel()

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

func Task(connInfo map[string]string, sudo bool, task string, args map[string]string) (*Result, error) {
cmdargs := []string{"bolt", "task", "run", "--nodes", connInfo["type"] + "://" + connInfo["host"], "-u", connInfo["user"]}
rodjek marked this conversation as resolved.
Show resolved Hide resolved

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, " "))
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