0
0
mirror of https://github.com/thegeeklab/wp-ansible.git synced 2024-11-09 17:10:41 +00:00
wp-ansible/plugin.go

390 lines
7.6 KiB
Go
Raw Normal View History

2021-01-26 11:28:47 +00:00
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"github.com/pkg/errors"
)
var ansibleFolder = "/etc/ansible"
var ansibleConfig = "/etc/ansible/ansible.cfg"
var ansibleContent = `
[defaults]
host_key_checking = False
`
type (
// Config for the plugin.
Config struct {
Requirements string
Galaxy string
Inventories []string
Playbooks []string
Limit string
SkipTags string
StartAtTask string
Tags string
ExtraVars []string
ModulePath []string
Check bool
Diff bool
FlushCache bool
ForceHandlers bool
ListHosts bool
ListTags bool
ListTasks bool
SyntaxCheck bool
Forks int
VaultID string
VaultPassword string
VaultPasswordFile string
Verbose int
PrivateKey string
PrivateKeyFile string
User string
Connection string
Timeout int
SSHCommonArgs string
SFTPExtraArgs string
SCPExtraArgs string
SSHExtraArgs string
Become bool
BecomeMethod string
BecomeUser string
}
// Plugin definition.
Plugin struct {
Config Config
}
)
// Exec provides the implementation of the plugin.
func (p *Plugin) Exec() error {
if err := p.playbooks(); err != nil {
return err
}
if err := p.ansibleConfig(); err != nil {
return err
}
if p.Config.PrivateKey != "" {
if err := p.privateKey(); err != nil {
return err
}
defer os.Remove(p.Config.PrivateKeyFile)
}
if p.Config.VaultPassword != "" {
if err := p.vaultPass(); err != nil {
return err
}
defer os.Remove(p.Config.VaultPasswordFile)
}
commands := []*exec.Cmd{
p.versionCommand(),
}
if p.Config.Requirements != "" {
commands = append(commands, p.requirementsCommand())
}
if p.Config.Galaxy != "" {
commands = append(commands, p.galaxyCommand())
}
for _, inventory := range p.Config.Inventories {
commands = append(commands, p.ansibleCommand(inventory))
}
for _, cmd := range commands {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "ANSIBLE_FORCE_COLOR=1")
trace(cmd)
if err := cmd.Run(); err != nil {
return err
}
}
return nil
}
func (p *Plugin) ansibleConfig() error {
if err := os.MkdirAll(ansibleFolder, os.ModePerm); err != nil {
return errors.Wrap(err, "failed to create ansible directory")
}
if err := ioutil.WriteFile(ansibleConfig, []byte(ansibleContent), 0600); err != nil {
return errors.Wrap(err, "failed to create ansible config")
}
return nil
}
func (p *Plugin) privateKey() error {
tmpfile, err := ioutil.TempFile("", "privateKey")
if err != nil {
return errors.Wrap(err, "failed to create private key file")
}
if _, err := tmpfile.Write([]byte(p.Config.PrivateKey)); err != nil {
return errors.Wrap(err, "failed to write private key file")
}
if err := tmpfile.Close(); err != nil {
return errors.Wrap(err, "failed to close private key file")
}
p.Config.PrivateKeyFile = tmpfile.Name()
return nil
}
func (p *Plugin) vaultPass() error {
tmpfile, err := ioutil.TempFile("", "vaultPass")
if err != nil {
return errors.Wrap(err, "failed to create vault password file")
}
if _, err := tmpfile.Write([]byte(p.Config.VaultPassword)); err != nil {
return errors.Wrap(err, "failed to write vault password file")
}
if err := tmpfile.Close(); err != nil {
return errors.Wrap(err, "failed to close vault password file")
}
p.Config.VaultPasswordFile = tmpfile.Name()
return nil
}
func (p *Plugin) playbooks() error {
var (
playbooks []string
)
for _, p := range p.Config.Playbooks {
files, err := filepath.Glob(p)
if err != nil {
playbooks = append(playbooks, p)
continue
}
playbooks = append(playbooks, files...)
}
if len(playbooks) == 0 {
return errors.New("failed to find playbook files")
}
p.Config.Playbooks = playbooks
return nil
}
func (p *Plugin) versionCommand() *exec.Cmd {
args := []string{
"--version",
}
return exec.Command(
"ansible",
args...,
)
}
func (p *Plugin) requirementsCommand() *exec.Cmd {
args := []string{
"install",
"--upgrade",
"--requirement",
p.Config.Requirements,
}
return exec.Command(
"pip",
args...,
)
}
func (p *Plugin) galaxyCommand() *exec.Cmd {
args := []string{
"install",
"--force",
"--role-file",
p.Config.Galaxy,
}
if p.Config.Verbose > 0 {
args = append(args, fmt.Sprintf("-%s", strings.Repeat("v", p.Config.Verbose)))
}
return exec.Command(
"ansible-galaxy",
args...,
)
}
func (p *Plugin) ansibleCommand(inventory string) *exec.Cmd {
args := []string{
"--inventory",
inventory,
}
if len(p.Config.ModulePath) > 0 {
args = append(args, "--module-path", strings.Join(p.Config.ModulePath, ":"))
}
if p.Config.VaultID != "" {
args = append(args, "--vault-id", p.Config.VaultID)
}
if p.Config.VaultPasswordFile != "" {
args = append(args, "--vault-password-file", p.Config.VaultPasswordFile)
}
for _, v := range p.Config.ExtraVars {
args = append(args, "--extra-vars", v)
}
if p.Config.ListHosts {
args = append(args, "--list-hosts")
args = append(args, p.Config.Playbooks...)
return exec.Command(
"ansible-playbook",
args...,
)
}
if p.Config.SyntaxCheck {
args = append(args, "--syntax-check")
args = append(args, p.Config.Playbooks...)
return exec.Command(
"ansible-playbook",
args...,
)
}
if p.Config.Check {
args = append(args, "--check")
}
if p.Config.Diff {
args = append(args, "--diff")
}
if p.Config.FlushCache {
args = append(args, "--flush-cache")
}
if p.Config.ForceHandlers {
args = append(args, "--force-handlers")
}
if p.Config.Forks != 5 {
args = append(args, "--forks", strconv.Itoa(p.Config.Forks))
}
if p.Config.Limit != "" {
args = append(args, "--limit", p.Config.Limit)
}
if p.Config.ListTags {
args = append(args, "--list-tags")
}
if p.Config.ListTasks {
args = append(args, "--list-tasks")
}
if p.Config.SkipTags != "" {
args = append(args, "--skip-tags", p.Config.SkipTags)
}
if p.Config.StartAtTask != "" {
args = append(args, "--start-at-task", p.Config.StartAtTask)
}
if p.Config.Tags != "" {
args = append(args, "--tags", p.Config.Tags)
}
if p.Config.PrivateKeyFile != "" {
args = append(args, "--private-key", p.Config.PrivateKeyFile)
}
if p.Config.User != "" {
args = append(args, "--user", p.Config.User)
}
if p.Config.Connection != "" {
args = append(args, "--connection", p.Config.Connection)
}
if p.Config.Timeout != 0 {
args = append(args, "--timeout", strconv.Itoa(p.Config.Timeout))
}
if p.Config.SSHCommonArgs != "" {
args = append(args, "--ssh-common-args", p.Config.SSHCommonArgs)
}
if p.Config.SFTPExtraArgs != "" {
args = append(args, "--sftp-extra-args", p.Config.SFTPExtraArgs)
}
if p.Config.SCPExtraArgs != "" {
args = append(args, "--scp-extra-args", p.Config.SCPExtraArgs)
}
if p.Config.SSHExtraArgs != "" {
args = append(args, "--ssh-extra-args", p.Config.SSHExtraArgs)
}
if p.Config.Become {
args = append(args, "--become")
}
if p.Config.BecomeMethod != "" {
args = append(args, "--become-method", p.Config.BecomeMethod)
}
if p.Config.BecomeUser != "" {
args = append(args, "--become-user", p.Config.BecomeUser)
}
if p.Config.Verbose > 0 {
args = append(args, fmt.Sprintf("-%s", strings.Repeat("v", p.Config.Verbose)))
}
args = append(args, p.Config.Playbooks...)
return exec.Command(
"ansible-playbook",
args...,
)
}
func trace(cmd *exec.Cmd) {
fmt.Println("$", strings.Join(cmd.Args, " "))
}