0
0
mirror of https://github.com/thegeeklab/wp-ansible.git synced 2024-09-20 01:12:46 +02:00
This commit is contained in:
Robert Kaussow 2021-01-26 12:28:47 +01:00
parent bd03b87e6c
commit 6b049439e5
No known key found for this signature in database
GPG Key ID: 65362AE74AF98B61
3 changed files with 664 additions and 3 deletions

View File

@ -36,6 +36,12 @@ def testing(ctx):
"commands": [ "commands": [
"go run honnef.co/go/tools/cmd/staticcheck ./...", "go run honnef.co/go/tools/cmd/staticcheck ./...",
], ],
"volumes": [
{
"name": "gopath",
"path": "/go",
},
],
}, },
{ {
"name": "lint", "name": "lint",
@ -43,7 +49,12 @@ def testing(ctx):
"commands": [ "commands": [
"go run golang.org/x/lint/golint -set_exit_status ./...", "go run golang.org/x/lint/golint -set_exit_status ./...",
], ],
"volumes": [
{
"name": "gopath",
"path": "/go",
},
],
}, },
{ {
"name": "vet", "name": "vet",
@ -51,6 +62,12 @@ def testing(ctx):
"commands": [ "commands": [
"go vet ./...", "go vet ./...",
], ],
"volumes": [
{
"name": "gopath",
"path": "/go",
},
],
}, },
{ {
"name": "test", "name": "test",
@ -58,6 +75,18 @@ def testing(ctx):
"commands": [ "commands": [
"go test -cover ./...", "go test -cover ./...",
], ],
"volumes": [
{
"name": "gopath",
"path": "/go",
},
],
},
],
"volumes": [
{
"name": "gopath",
"temp": {},
}, },
], ],
"trigger": { "trigger": {
@ -72,11 +101,11 @@ def testing(ctx):
def linux(ctx, arch): def linux(ctx, arch):
if ctx.build.event == "tag": if ctx.build.event == "tag":
build = [ build = [
'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-ansible ./cmd/drone-ansible' % (ctx.build.ref.replace("refs/tags/v", ""), arch), 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-ansible .' % (ctx.build.ref.replace("refs/tags/v", ""), arch),
] ]
else: else:
build = [ build = [
'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-ansible ./cmd/drone-ansible' % (ctx.build.commit[0:8], arch), 'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/drone-ansible .' % (ctx.build.commit[0:8], arch),
] ]
steps = [ steps = [

243
main.go Normal file
View File

@ -0,0 +1,243 @@
package main
import (
"log"
"os"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
version = "unknown"
)
func main() {
app := cli.NewApp()
app.Name = "ansible plugin"
app.Usage = "ansible plugin"
app.Action = run
app.Version = version
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "requirements",
Usage: "path to python requirements",
EnvVar: "PLUGIN_REQUIREMENTS",
},
cli.StringFlag{
Name: "galaxy",
Usage: "path to galaxy requirements",
EnvVar: "PLUGIN_GALAXY",
},
cli.StringSliceFlag{
Name: "inventory",
Usage: "specify inventory host path",
EnvVar: "PLUGIN_INVENTORY,PLUGIN_INVENTORIES",
},
cli.StringSliceFlag{
Name: "playbook",
Usage: "list of playbooks to apply",
EnvVar: "PLUGIN_PLAYBOOK,PLUGIN_PLAYBOOKS",
},
cli.StringFlag{
Name: "limit",
Usage: "further limit selected hosts to an additional pattern",
EnvVar: "PLUGIN_LIMIT",
},
cli.StringFlag{
Name: "skip-tags",
Usage: "only run plays and tasks whose tags do not match",
EnvVar: "PLUGIN_SKIP_TAGS",
},
cli.StringFlag{
Name: "start-at-task",
Usage: "start the playbook at the task matching this name",
EnvVar: "PLUGIN_START_AT_TASK",
},
cli.StringFlag{
Name: "tags",
Usage: "only run plays and tasks tagged with these values",
EnvVar: "PLUGIN_TAGS",
},
cli.StringSliceFlag{
Name: "extra-vars",
Usage: "set additional variables as key=value",
EnvVar: "PLUGIN_EXTRA_VARS,ANSIBLE_EXTRA_VARS",
},
cli.StringSliceFlag{
Name: "module-path",
Usage: "prepend paths to module library",
EnvVar: "PLUGIN_MODULE_PATH",
},
cli.BoolFlag{
Name: "check",
Usage: "run a check, do not apply any changes",
EnvVar: "PLUGIN_CHECK",
},
cli.BoolFlag{
Name: "diff",
Usage: "show the differences, may print secrets",
EnvVar: "PLUGIN_DIFF",
},
cli.BoolFlag{
Name: "flush-cache",
Usage: "clear the fact cache for every host in inventory",
EnvVar: "PLUGIN_FLUSH_CACHE",
},
cli.BoolFlag{
Name: "force-handlers",
Usage: "run handlers even if a task fails",
EnvVar: "PLUGIN_FORCE_HANDLERS",
},
cli.BoolFlag{
Name: "list-hosts",
Usage: "outputs a list of matching hosts",
EnvVar: "PLUGIN_LIST_HOSTS",
},
cli.BoolFlag{
Name: "list-tags",
Usage: "list all available tags",
EnvVar: "PLUGIN_LIST_TAGS",
},
cli.BoolFlag{
Name: "list-tasks",
Usage: "list all tasks that would be executed",
EnvVar: "PLUGIN_LIST_TASKS",
},
cli.BoolFlag{
Name: "syntax-check",
Usage: "perform a syntax check on the playbook",
EnvVar: "PLUGIN_SYNTAX_CHECK",
},
cli.IntFlag{
Name: "forks",
Usage: "specify number of parallel processes to use",
EnvVar: "PLUGIN_FORKS",
Value: 5,
},
cli.StringFlag{
Name: "vault-id",
Usage: "the vault identity to use",
EnvVar: "PLUGIN_VAULT_ID,ANSIBLE_VAULT_ID",
},
cli.StringFlag{
Name: "vault-password",
Usage: "the vault password to use",
EnvVar: "PLUGIN_VAULT_PASSWORD,ANSIBLE_VAULT_PASSWORD",
},
cli.IntFlag{
Name: "verbose",
Usage: "level of verbosity, 0 up to 4",
EnvVar: "PLUGIN_VERBOSE",
},
cli.StringFlag{
Name: "private-key",
Usage: "use this key to authenticate the connection",
EnvVar: "PLUGIN_PRIVATE_KEY,ANSIBLE_PRIVATE_KEY",
},
cli.StringFlag{
Name: "user",
Usage: "connect as this user",
EnvVar: "PLUGIN_USER,ANSIBLE_USER",
},
cli.StringFlag{
Name: "connection",
Usage: "connection type to use",
EnvVar: "PLUGIN_CONNECTION",
},
cli.IntFlag{
Name: "timeout",
Usage: "override the connection timeout in seconds",
EnvVar: "PLUGIN_TIMEOUT",
},
cli.StringFlag{
Name: "ssh-common-args",
Usage: "specify common arguments to pass to sftp/scp/ssh",
EnvVar: "PLUGIN_SSH_COMMON_ARGS",
},
cli.StringFlag{
Name: "sftp-extra-args",
Usage: "specify extra arguments to pass to sftp only",
EnvVar: "PLUGIN_SFTP_EXTRA_ARGS",
},
cli.StringFlag{
Name: "scp-extra-args",
Usage: "specify extra arguments to pass to scp only",
EnvVar: "PLUGIN_SCP_EXTRA_ARGS",
},
cli.StringFlag{
Name: "ssh-extra-args",
Usage: "specify extra arguments to pass to ssh only",
EnvVar: "PLUGIN_SSH_EXTRA_ARGS",
},
cli.BoolFlag{
Name: "become",
Usage: "run operations with become",
EnvVar: "PLUGIN_BECOME",
},
cli.StringFlag{
Name: "become-method",
Usage: "privilege escalation method to use",
EnvVar: "PLUGIN_BECOME_METHOD,ANSIBLE_BECOME_METHOD",
},
cli.StringFlag{
Name: "become-user",
Usage: "run operations as this user",
EnvVar: "PLUGIN_BECOME_USER,ANSIBLE_BECOME_USER",
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
func run(c *cli.Context) error {
plugin := Plugin{
Config: Config{
Requirements: c.String("requirements"),
Galaxy: c.String("galaxy"),
Inventories: c.StringSlice("inventory"),
Playbooks: c.StringSlice("playbook"),
Limit: c.String("limit"),
SkipTags: c.String("skip-tags"),
StartAtTask: c.String("start-at-task"),
Tags: c.String("tags"),
ExtraVars: c.StringSlice("extra-vars"),
ModulePath: c.StringSlice("module-path"),
Check: c.Bool("check"),
Diff: c.Bool("diff"),
FlushCache: c.Bool("flush-cache"),
ForceHandlers: c.Bool("force-handlers"),
ListHosts: c.Bool("list-hosts"),
ListTags: c.Bool("list-tags"),
ListTasks: c.Bool("list-tasks"),
SyntaxCheck: c.Bool("syntax-check"),
Forks: c.Int("forks"),
VaultID: c.String("vailt-id"),
VaultPassword: c.String("vault-password"),
Verbose: c.Int("verbose"),
PrivateKey: c.String("private-key"),
User: c.String("user"),
Connection: c.String("connection"),
Timeout: c.Int("timeout"),
SSHCommonArgs: c.String("ssh-common-args"),
SFTPExtraArgs: c.String("sftp-extra-args"),
SCPExtraArgs: c.String("scp-extra-args"),
SSHExtraArgs: c.String("ssh-extra-args"),
Become: c.Bool("become"),
BecomeMethod: c.String("become-method"),
BecomeUser: c.String("become-user"),
},
}
if len(plugin.Config.Playbooks) == 0 {
return errors.New("you must provide a playbook")
}
if len(plugin.Config.Inventories) == 0 {
return errors.New("you must provide an inventory")
}
return plugin.Exec()
}

389
plugin.go Normal file
View File

@ -0,0 +1,389 @@
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, " "))
}