mirror of
https://github.com/thegeeklab/wp-ansible.git
synced 2024-11-21 13:40:39 +00:00
refactor: rewrite to use plugin boilerplate (#12)
* refactor: rewrite to use plugin boilerplate * fix build source * fix gitignore
This commit is contained in:
parent
3436b3eb77
commit
e80ca3a599
@ -101,11 +101,11 @@ def testing(ctx):
|
||||
def linux(ctx, arch):
|
||||
if ctx.build.event == "tag":
|
||||
build = [
|
||||
'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),
|
||||
'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),
|
||||
]
|
||||
else:
|
||||
build = [
|
||||
'go build -v -ldflags "-X main.version=%s" -a -tags netgo -o release/linux/%s/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 ./cmd/drone-ansible' % (ctx.build.commit[0:8], arch),
|
||||
]
|
||||
|
||||
steps = [
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,5 +1,5 @@
|
||||
release/
|
||||
/release/
|
||||
/drone-ansible*
|
||||
|
||||
coverage.out
|
||||
drone-ansible
|
||||
.drone.yml
|
||||
|
211
cmd/drone-ansible/config.go
Normal file
211
cmd/drone-ansible/config.go
Normal file
@ -0,0 +1,211 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/owncloud-ci/drone-ansible/plugin"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// settingsFlags has the cli.Flags for the plugin.Settings.
|
||||
func settingsFlags(settings *plugin.Settings) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "requirements",
|
||||
Usage: "path to python requirements",
|
||||
EnvVars: []string{"PLUGIN_REQUIREMENTS"},
|
||||
Destination: &settings.Requirements,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "galaxy",
|
||||
Usage: "path to galaxy requirements",
|
||||
EnvVars: []string{"PLUGIN_GALAXY"},
|
||||
Destination: &settings.Galaxy,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "inventory",
|
||||
Usage: "specify inventory host path",
|
||||
EnvVars: []string{"PLUGIN_INVENTORY", "PLUGIN_INVENTORIES"},
|
||||
Destination: &settings.Inventories,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "playbook",
|
||||
Usage: "list of playbooks to apply",
|
||||
EnvVars: []string{"PLUGIN_PLAYBOOK", "PLUGIN_PLAYBOOKS"},
|
||||
Destination: &settings.Playbooks,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "limit",
|
||||
Usage: "further limit selected hosts to an additional pattern",
|
||||
EnvVars: []string{"PLUGIN_LIMIT"},
|
||||
Destination: &settings.Limit,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "skip-tags",
|
||||
Usage: "only run plays and tasks whose tags do not match",
|
||||
EnvVars: []string{"PLUGIN_SKIP_TAGS"},
|
||||
Destination: &settings.SkipTags,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "start-at-task",
|
||||
Usage: "start the playbook at the task matching this name",
|
||||
EnvVars: []string{"PLUGIN_START_AT_TASK"},
|
||||
Destination: &settings.StartAtTask,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "tags",
|
||||
Usage: "only run plays and tasks tagged with these values",
|
||||
EnvVars: []string{"PLUGIN_TAGS"},
|
||||
Destination: &settings.Tags,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "extra-vars",
|
||||
Usage: "set additional variables as key=value",
|
||||
EnvVars: []string{"PLUGIN_EXTRA_VARS", "ANSIBLE_EXTRA_VARS"},
|
||||
Destination: &settings.ExtraVars,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "module-path",
|
||||
Usage: "prepend paths to module library",
|
||||
EnvVars: []string{"PLUGIN_MODULE_PATH"},
|
||||
Destination: &settings.ModulePath,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "check",
|
||||
Usage: "run a check, do not apply any changes",
|
||||
EnvVars: []string{"PLUGIN_CHECK"},
|
||||
Destination: &settings.Check,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "diff",
|
||||
Usage: "show the differences, may print secrets",
|
||||
EnvVars: []string{"PLUGIN_DIFF"},
|
||||
Destination: &settings.Diff,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "flush-cache",
|
||||
Usage: "clear the fact cache for every host in inventory",
|
||||
EnvVars: []string{"PLUGIN_FLUSH_CACHE"},
|
||||
Destination: &settings.FlushCache,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "force-handlers",
|
||||
Usage: "run handlers even if a task fails",
|
||||
EnvVars: []string{"PLUGIN_FORCE_HANDLERS"},
|
||||
Destination: &settings.ForceHandlers,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "list-hosts",
|
||||
Usage: "outputs a list of matching hosts",
|
||||
EnvVars: []string{"PLUGIN_LIST_HOSTS"},
|
||||
Destination: &settings.ListHosts,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "list-tags",
|
||||
Usage: "list all available tags",
|
||||
EnvVars: []string{"PLUGIN_LIST_TAGS"},
|
||||
Destination: &settings.ListTags,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "list-tasks",
|
||||
Usage: "list all tasks that would be executed",
|
||||
EnvVars: []string{"PLUGIN_LIST_TASKS"},
|
||||
Destination: &settings.ListTasks,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "syntax-check",
|
||||
Usage: "perform a syntax check on the playbook",
|
||||
EnvVars: []string{"PLUGIN_SYNTAX_CHECK"},
|
||||
Destination: &settings.SyntaxCheck,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "forks",
|
||||
Usage: "specify number of parallel processes to use",
|
||||
EnvVars: []string{"PLUGIN_FORKS"},
|
||||
Value: 5,
|
||||
Destination: &settings.Forks,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "vault-id",
|
||||
Usage: "the vault identity to use",
|
||||
EnvVars: []string{"PLUGIN_VAULT_ID", "ANSIBLE_VAULT_ID"},
|
||||
Destination: &settings.VaultID,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "vault-password",
|
||||
Usage: "the vault password to use",
|
||||
EnvVars: []string{"PLUGIN_VAULT_PASSWORD", "ANSIBLE_VAULT_PASSWORD"},
|
||||
Destination: &settings.VaultPassword,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "verbose",
|
||||
Usage: "level of verbosity, 0 up to 4",
|
||||
EnvVars: []string{"PLUGIN_VERBOSE"},
|
||||
Destination: &settings.Verbose,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "private-key",
|
||||
Usage: "use this key to authenticate the connection",
|
||||
EnvVars: []string{"PLUGIN_PRIVATE_KEY", "ANSIBLE_PRIVATE_KEY"},
|
||||
Destination: &settings.PrivateKey,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "user",
|
||||
Usage: "connect as this user",
|
||||
EnvVars: []string{"PLUGIN_USER", "ANSIBLE_USER"},
|
||||
Destination: &settings.User,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "connection",
|
||||
Usage: "connection type to use",
|
||||
EnvVars: []string{"PLUGIN_CONNECTION"},
|
||||
Destination: &settings.Connection,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "timeout",
|
||||
Usage: "override the connection timeout in seconds",
|
||||
EnvVars: []string{"PLUGIN_TIMEOUT"},
|
||||
Destination: &settings.Timeout,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ssh-common-args",
|
||||
Usage: "specify common arguments to pass to sftp/scp/ssh",
|
||||
EnvVars: []string{"PLUGIN_SSH_COMMON_ARGS"},
|
||||
Destination: &settings.SSHCommonArgs,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "sftp-extra-args",
|
||||
Usage: "specify extra arguments to pass to sftp only",
|
||||
EnvVars: []string{"PLUGIN_SFTP_EXTRA_ARGS"},
|
||||
Destination: &settings.SFTPExtraArgs,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "scp-extra-args",
|
||||
Usage: "specify extra arguments to pass to scp only",
|
||||
EnvVars: []string{"PLUGIN_SCP_EXTRA_ARGS"},
|
||||
Destination: &settings.SCPExtraArgs,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ssh-extra-args",
|
||||
Usage: "specify extra arguments to pass to ssh only",
|
||||
EnvVars: []string{"PLUGIN_SSH_EXTRA_ARGS"},
|
||||
Destination: &settings.SSHExtraArgs,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "become",
|
||||
Usage: "run operations with become",
|
||||
EnvVars: []string{"PLUGIN_BECOME"},
|
||||
Destination: &settings.Become,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "become-method",
|
||||
Usage: "privilege escalation method to use",
|
||||
EnvVars: []string{"PLUGIN_BECOME_METHOD", "ANSIBLE_BECOME_METHOD"},
|
||||
Destination: &settings.BecomeMethod,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "become-user",
|
||||
Usage: "run operations as this user",
|
||||
EnvVars: []string{"PLUGIN_BECOME_USER", "ANSIBLE_BECOME_USER"},
|
||||
Destination: &settings.BecomeUser,
|
||||
},
|
||||
}
|
||||
}
|
64
cmd/drone-ansible/main.go
Normal file
64
cmd/drone-ansible/main.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/owncloud-ci/drone-ansible/plugin"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/drone-plugins/drone-plugin-lib/errors"
|
||||
"github.com/drone-plugins/drone-plugin-lib/urfave"
|
||||
)
|
||||
|
||||
var version = "unknown"
|
||||
|
||||
func main() {
|
||||
settings := &plugin.Settings{}
|
||||
|
||||
if _, err := os.Stat("/run/drone/env"); err == nil {
|
||||
godotenv.Overload("/run/drone/env")
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "drone-ansible",
|
||||
Usage: "provision infrastructure with Ansible",
|
||||
Version: version,
|
||||
Flags: append(settingsFlags(settings), urfave.Flags()...),
|
||||
Action: run(settings),
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
errors.HandleExit(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run(settings *plugin.Settings) cli.ActionFunc {
|
||||
return func(ctx *cli.Context) error {
|
||||
urfave.LoggingFromContext(ctx)
|
||||
|
||||
plugin := plugin.New(
|
||||
*settings,
|
||||
urfave.PipelineFromContext(ctx),
|
||||
urfave.NetworkFromContext(ctx),
|
||||
)
|
||||
|
||||
if err := plugin.Validate(); err != nil {
|
||||
if e, ok := err.(errors.ExitCoder); ok {
|
||||
return e
|
||||
}
|
||||
|
||||
return errors.ExitMessagef("validation failed: %w", err)
|
||||
}
|
||||
|
||||
if err := plugin.Execute(); err != nil {
|
||||
if e, ok := err.(errors.ExitCoder); ok {
|
||||
return e
|
||||
}
|
||||
|
||||
return errors.ExitMessagef("execution failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
6
go.mod
6
go.mod
@ -4,7 +4,11 @@ go 1.15
|
||||
|
||||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/drone-plugins/drone-plugin-lib v0.4.0
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/urfave/cli v1.22.5
|
||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
|
||||
)
|
||||
|
36
go.sum
36
go.sum
@ -4,8 +4,19 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/drone-plugins/drone-plugin-lib v0.4.0 h1:qywEYGhquUuid6zNLmKia8CWY1TUa8jPQQ/G9ozfAmc=
|
||||
github.com/drone-plugins/drone-plugin-lib v0.4.0/go.mod h1:EgqogX38GoJFtckeSQyhBJYX8P+KWBPhdprAVvyRxF8=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@ -13,7 +24,28 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
|
243
main.go
243
main.go
@ -1,243 +0,0 @@
|
||||
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
389
plugin.go
@ -1,389 +0,0 @@
|
||||
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, " "))
|
||||
}
|
285
plugin/ansible.go
Normal file
285
plugin/ansible.go
Normal file
@ -0,0 +1,285 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var ansibleFolder = "/etc/ansible"
|
||||
var ansibleConfig = "/etc/ansible/ansible.cfg"
|
||||
|
||||
var ansibleContent = `
|
||||
[defaults]
|
||||
host_key_checking = False
|
||||
`
|
||||
|
||||
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.settings.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.settings.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.settings.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.settings.VaultPasswordFile = tmpfile.Name()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Plugin) playbooks() error {
|
||||
var (
|
||||
playbooks []string
|
||||
)
|
||||
|
||||
for _, p := range p.settings.Playbooks.Value() {
|
||||
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.settings.Playbooks = *cli.NewStringSlice(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.settings.Requirements,
|
||||
}
|
||||
|
||||
return exec.Command(
|
||||
"pip",
|
||||
args...,
|
||||
)
|
||||
}
|
||||
|
||||
func (p *Plugin) galaxyCommand() *exec.Cmd {
|
||||
args := []string{
|
||||
"install",
|
||||
"--force",
|
||||
"--role-file",
|
||||
p.settings.Galaxy,
|
||||
}
|
||||
|
||||
if p.settings.Verbose > 0 {
|
||||
args = append(args, fmt.Sprintf("-%s", strings.Repeat("v", p.settings.Verbose)))
|
||||
}
|
||||
|
||||
return exec.Command(
|
||||
"ansible-galaxy",
|
||||
args...,
|
||||
)
|
||||
}
|
||||
|
||||
func (p *Plugin) ansibleCommand(inventory string) *exec.Cmd {
|
||||
args := []string{
|
||||
"--inventory",
|
||||
inventory,
|
||||
}
|
||||
|
||||
if len(p.settings.ModulePath.Value()) > 0 {
|
||||
args = append(args, "--module-path", strings.Join(p.settings.ModulePath.Value(), ":"))
|
||||
}
|
||||
|
||||
if p.settings.VaultID != "" {
|
||||
args = append(args, "--vault-id", p.settings.VaultID)
|
||||
}
|
||||
|
||||
if p.settings.VaultPasswordFile != "" {
|
||||
args = append(args, "--vault-password-file", p.settings.VaultPasswordFile)
|
||||
}
|
||||
|
||||
for _, v := range p.settings.ExtraVars.Value() {
|
||||
args = append(args, "--extra-vars", v)
|
||||
}
|
||||
|
||||
if p.settings.ListHosts {
|
||||
args = append(args, "--list-hosts")
|
||||
args = append(args, p.settings.Playbooks.Value()...)
|
||||
|
||||
return exec.Command(
|
||||
"ansible-playbook",
|
||||
args...,
|
||||
)
|
||||
}
|
||||
|
||||
if p.settings.SyntaxCheck {
|
||||
args = append(args, "--syntax-check")
|
||||
args = append(args, p.settings.Playbooks.Value()...)
|
||||
|
||||
return exec.Command(
|
||||
"ansible-playbook",
|
||||
args...,
|
||||
)
|
||||
}
|
||||
|
||||
if p.settings.Check {
|
||||
args = append(args, "--check")
|
||||
}
|
||||
|
||||
if p.settings.Diff {
|
||||
args = append(args, "--diff")
|
||||
}
|
||||
|
||||
if p.settings.FlushCache {
|
||||
args = append(args, "--flush-cache")
|
||||
}
|
||||
|
||||
if p.settings.ForceHandlers {
|
||||
args = append(args, "--force-handlers")
|
||||
}
|
||||
|
||||
if p.settings.Forks != 5 {
|
||||
args = append(args, "--forks", strconv.Itoa(p.settings.Forks))
|
||||
}
|
||||
|
||||
if p.settings.Limit != "" {
|
||||
args = append(args, "--limit", p.settings.Limit)
|
||||
}
|
||||
|
||||
if p.settings.ListTags {
|
||||
args = append(args, "--list-tags")
|
||||
}
|
||||
|
||||
if p.settings.ListTasks {
|
||||
args = append(args, "--list-tasks")
|
||||
}
|
||||
|
||||
if p.settings.SkipTags != "" {
|
||||
args = append(args, "--skip-tags", p.settings.SkipTags)
|
||||
}
|
||||
|
||||
if p.settings.StartAtTask != "" {
|
||||
args = append(args, "--start-at-task", p.settings.StartAtTask)
|
||||
}
|
||||
|
||||
if p.settings.Tags != "" {
|
||||
args = append(args, "--tags", p.settings.Tags)
|
||||
}
|
||||
|
||||
if p.settings.PrivateKeyFile != "" {
|
||||
args = append(args, "--private-key", p.settings.PrivateKeyFile)
|
||||
}
|
||||
|
||||
if p.settings.User != "" {
|
||||
args = append(args, "--user", p.settings.User)
|
||||
}
|
||||
|
||||
if p.settings.Connection != "" {
|
||||
args = append(args, "--connection", p.settings.Connection)
|
||||
}
|
||||
|
||||
if p.settings.Timeout != 0 {
|
||||
args = append(args, "--timeout", strconv.Itoa(p.settings.Timeout))
|
||||
}
|
||||
|
||||
if p.settings.SSHCommonArgs != "" {
|
||||
args = append(args, "--ssh-common-args", p.settings.SSHCommonArgs)
|
||||
}
|
||||
|
||||
if p.settings.SFTPExtraArgs != "" {
|
||||
args = append(args, "--sftp-extra-args", p.settings.SFTPExtraArgs)
|
||||
}
|
||||
|
||||
if p.settings.SCPExtraArgs != "" {
|
||||
args = append(args, "--scp-extra-args", p.settings.SCPExtraArgs)
|
||||
}
|
||||
|
||||
if p.settings.SSHExtraArgs != "" {
|
||||
args = append(args, "--ssh-extra-args", p.settings.SSHExtraArgs)
|
||||
}
|
||||
|
||||
if p.settings.Become {
|
||||
args = append(args, "--become")
|
||||
}
|
||||
|
||||
if p.settings.BecomeMethod != "" {
|
||||
args = append(args, "--become-method", p.settings.BecomeMethod)
|
||||
}
|
||||
|
||||
if p.settings.BecomeUser != "" {
|
||||
args = append(args, "--become-user", p.settings.BecomeUser)
|
||||
}
|
||||
|
||||
if p.settings.Verbose > 0 {
|
||||
args = append(args, fmt.Sprintf("-%s", strings.Repeat("v", p.settings.Verbose)))
|
||||
}
|
||||
|
||||
args = append(args, p.settings.Playbooks.Value()...)
|
||||
|
||||
return exec.Command(
|
||||
"ansible-playbook",
|
||||
args...,
|
||||
)
|
||||
}
|
||||
|
||||
func trace(cmd *exec.Cmd) {
|
||||
fmt.Println("$", strings.Join(cmd.Args, " "))
|
||||
}
|
120
plugin/impl.go
Normal file
120
plugin/impl.go
Normal file
@ -0,0 +1,120 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Settings for the Plugin.
|
||||
type Settings struct {
|
||||
Requirements string
|
||||
Galaxy string
|
||||
Inventories cli.StringSlice
|
||||
Playbooks cli.StringSlice
|
||||
Limit string
|
||||
SkipTags string
|
||||
StartAtTask string
|
||||
Tags string
|
||||
ExtraVars cli.StringSlice
|
||||
ModulePath cli.StringSlice
|
||||
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
|
||||
}
|
||||
|
||||
// Validate handles the settings validation of the plugin.
|
||||
func (p *Plugin) Validate() error {
|
||||
if len(p.settings.Playbooks.Value()) == 0 {
|
||||
return errors.New("you must provide a playbook")
|
||||
}
|
||||
|
||||
if len(p.settings.Inventories.Value()) == 0 {
|
||||
return errors.New("you must provide an inventory")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execute provides the implementation of the plugin.
|
||||
func (p *Plugin) Execute() error {
|
||||
if err := p.playbooks(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.ansibleConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.settings.PrivateKey != "" {
|
||||
if err := p.privateKey(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(p.settings.PrivateKeyFile)
|
||||
}
|
||||
|
||||
if p.settings.VaultPassword != "" {
|
||||
if err := p.vaultPass(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer os.Remove(p.settings.VaultPasswordFile)
|
||||
}
|
||||
|
||||
commands := []*exec.Cmd{
|
||||
p.versionCommand(),
|
||||
}
|
||||
|
||||
if p.settings.Requirements != "" {
|
||||
commands = append(commands, p.requirementsCommand())
|
||||
}
|
||||
|
||||
if p.settings.Galaxy != "" {
|
||||
commands = append(commands, p.galaxyCommand())
|
||||
}
|
||||
|
||||
for _, inventory := range p.settings.Inventories.Value() {
|
||||
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
|
||||
}
|
21
plugin/plugin.go
Normal file
21
plugin/plugin.go
Normal file
@ -0,0 +1,21 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/drone-plugins/drone-plugin-lib/drone"
|
||||
)
|
||||
|
||||
// Plugin implements drone.Plugin to provide the plugin implementation.
|
||||
type Plugin struct {
|
||||
settings Settings
|
||||
pipeline drone.Pipeline
|
||||
network drone.Network
|
||||
}
|
||||
|
||||
// New initializes a plugin from the given Settings, Pipeline, and Network.
|
||||
func New(settings Settings, pipeline drone.Pipeline, network drone.Network) drone.Plugin {
|
||||
return &Plugin{
|
||||
settings: settings,
|
||||
pipeline: pipeline,
|
||||
network: network,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user