Need help with go-ansible?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

apenella
313 Stars 52 Forks MIT License 165 Commits 4 Opened issues

Description

Go-ansible is a package for running ansible-playbook or ansible commands from Golang applications.

Services available

!
?

Need anything else?

Contributors list

go-ansible-logo

go-ansible

Go-ansible is a package for running

ansible-playbook
or
ansible
commands from Golang applications. It supports the most of its options for each command.

Install

To install the latest stable version run the command below:

$ go get github.com/apenella/[email protected]

Upgrade to 1.x

Since

go-ansible
v1.0.0 has introduced many breaking changes read the changelog and the upgrade guide carefully before to proceed to the upgrade.

Packages

Adhoc

github.com/apenella/go-ansible/pkg/adhoc
package enables you to run
ansible
adhoc commands. You can use these
adhoc
types to run ansible commands:
  • AnsibleAdhocCmd is the main object type which defines the
    ansible
    adhoc command and how to execute it.
    AnsibleAdhocCmd
    definition is mandatory to run any
    ansible
    adhoc command.
    AnsibleAdhocCmd
    has a parameter that defines the
    Executor
    to use, the worker that launches the execution. If no
    Executor
    is specified, is used a bare
    DefaultExecutor
    .
  • AnsibleAdhocOptions type has those parameters described on
    Options
    section within ansible's man page, and defines how should be the
    ansible
    execution behavior and where to find execution configuration.

You could also provide to

AnsiblePlaybookCmd
privilege escalation options or connection options, defined in
github.com/apenella/go-ansible/pkg/options

Playbook

github.com/apenella/go-ansible/pkg/playbook
package lets you run
ansible-playbook
commands. You can use these
playbook
types to run ansible playbooks:
  • AnsiblePlaybookCmd is the main object type which defines the
    ansible-playbook
    command and how to execute it.
    AnsiblePlaybookCmd
    definition is mandatory to run any
    ansible-playbook
    command.
    AnsiblePlaybookCmd
    has a parameter that defines the
    Executor
    to use, the worker that launches the execution. If no
    Executor
    is specified, a bare
    DefaultExecutor
    is used.
  • AnsiblePlaybookOptions type has those parameters described on
    Options
    section within ansible-playbook's man page, and defines how should be the
    ansible-playbook
    execution behavior and where to find execution configuration.

You could also provide to

AnsiblePlaybookCmd
escalation privileged options or connection options, defined in
github.com/apenella/go-ansible/pkg/options
.

Execute

An executor is the component in charge to run the command and return the result received on stdout and stderr. Go-ansible has a default executor implementation under

execute
package. That executor is named
DefaultExecute
.

Any executor must comply to the

Executor
interface.
go
// Executor interface is satisfied by those types which has a Execute(context.Context,[]string,stdoutcallback.StdoutCallbackResultsFunc,...ExecuteOptions)error method
type Executor interface {
    Execute(ctx context.Context, command []string, resultsFunc stdoutcallback.StdoutCallbackResultsFunc, options ...ExecuteOptions) error
}

DefaultExecute

DefaultExecutor
is the executor defined in the go-ansible library. On its most basic setup it just writes the command stdout to system stdout and the same for stderr, but its easy to extend the way of managing the command stdout and stderr. To extend and update its behavior it comes with a bunch of
ExecuteOptions
functions which can be passed to the executor.
go
// ExecuteOptions is a function to set executor options
type ExecuteOptions func(Executor)

Another way to extend how to return the results to the user is by using

transformers
, which can also be added to
DefaultExecutor
through
WithTransformers( ...results.TransformerFunc) ExecuteOptions

Take a look to the examples to see how to do that.

Custom executor

You could write your own executor implementation and set it on

AnsiblePlaybookCmd
object, whenever
DefaultExecutor
does not fits to your needs.
AnsiblePlaybookCmd
expects an object that implements the
Executor
interface.

Below there is an example of a custom executor which could be configured by

ExecuteOptions
functions. ```go type MyExecutor struct { Prefix string }

// Options method is used as a helper to apply a bunch of options to executor func (e *MyExecutor) Options(options ...execute.ExecuteOptions) { // apply all options to the executor for _, opt := range options { opt(e) } }

// WithPrefix method is used to set the executor prefix attribute func WithPrefix(prefix string) execute.ExecuteOptions { return func(e execute.Executor) { e.(*MyExecutor).Prefix = prefix } }

func (e *MyExecutor) Execute(ctx context.Context, command []string, resultsFunc stdoutcallback.StdoutCallbackResultsFunc, options ...execute.ExecuteOptions) error { // It is possible to apply extra options when Execute is called for _, opt := range options { opt(e) } // that's a dummy work fmt.Println(fmt.Sprintf("[%s] %s\n", e.Prefix, "I am MyExecutor and I am doing nothing")) return nil } ```

Finally, on the next snipped is executed the

ansible-playbook
using the custom executor ```go // define an instance for the new executor and set the options exe := &MyExecutor{}

exe.Options( WithPrefix("Go ansible example"), )

playbook := &ansibler.AnsiblePlaybookCmd{ Playbook: "site.yml", ConnectionOptions: ansiblePlaybookConnectionOptions, Options: ansiblePlaybookOptions, Exec: exe, }

playbook.Run(context.TODO()) ```

When you run the playbook using your dummy executor, the output will be as follows:

$ go run myexecutor-ansibleplaybook.go
[Go ansible example] I am MyExecutor and I am doing nothing

Options

The types to define command execution options can be found in

github.com/apenella/go-ansible/pkg/options
.

ansible adhoc and ansible-playbook common options

  • AnsibleConnectionOptions object has those parameters described on
    Connections Options
    section within ansible-playbook's man page, and defines how to connect to hosts.
  • AnsiblePrivilegeEscalationOptions object has those parameters described on
    Escalation Options
    section within ansible-playbook's man page, and defines how to become a user.

Stdout Callback

It is possible to define and specific stdout callback method on

go-ansible
. You can set the
StdoutCallback
attribute on
AnsiblePlaybookCmd
object. Depending on the used method, the results are managed by one function or another. The functions to manage
ansible-playbook
's output are defined in the package
github.com/apenella/go-ansible/pkg/stdoutcallback/results
and must be defined following the next signature:
go
// StdoutCallbackResultsFunc defines a function which manages ansible's stdout callbacks. The function expects a context, a reader that receives the data to be wrote and a writer that defines where to write the data coming from reader, Finally a list of transformers could be passed to update the output coming from the executor.
type StdoutCallbackResultsFunc func(context.Context, io.Reader, io.Writer, ...results.TransformerFunc) error

Results

Below are described the methods to manage ansible playbooks outputs:

Transformers

A transformer is a function which purpose is to enrich or update the output coming from the executor, and are defined by the type

TransformerFunc
.
go
// TransformerFunc is used to enrich or update messages before to be printed out
type TransformerFunc func(string) string

The output coming from executor is processed line by line and is on that step where are applied all the transformers.

results
package provides a set of transformers ready to be used, but can also defined by your own and passed through executor.
  • Prepend: Sets a prefix string to the output line
  • Append: Sets a suffix string to the output line
  • LogFormat: Include date time prefix to the output line
  • IgnoreMessage: Ignores the output line based on the patterns it receives as input parameters

Default

By default, any stdout callback results is managed by DefaultStdoutCallbackResults results method. That results method prepends the separator string

──
tho each line on stdout, when any transformer is defined, and prepare all the transformers before to call the worker function, which is in charge to write the output to io.Writer.

JSON

When the stdout callback method is defined to be in json format, the output is managed by JSONStdoutCallbackResults results method. That results method prepares the worker output function to use the

IgnoreMessage
transformer, to ignore those non json lines. Any other transformer will be ignored but
JSONStdoutCallbackResults

On JSONStdoutCallbackResults function is defined the

skipPatterns
array where are placed the matching expressions for the lines to be ignored.
go
skipPatterns := []string{
        // This pattern skips timer's callback whitelist output
        "^[\\s\\t]*Playbook run took [0-9]+ days, [0-9]+ hours, [0-9]+ minutes, [0-9]+ seconds$",
    }
Manage JSON output

JSONStdoutCallbackResults method writes to io.Writer parameter the json output. Results packages provides a JSONParser that returns an AnsiblePlaybookJSONResults, holding the unmarshalled json on it. You could manipulate AnsiblePlaybookJSONResults object to achieve and format the json output depending on your needs.

The json schema expected from

ansible-playbook
is the defined in https://github.com/ansible/ansible/blob/v2.9.11/lib/ansible/plugins/callback/json.py.

Examples

Below you could find an step by step example of how to use

go-ansible
but on examples folder there are more examples.

When is needed to run an

ansible-playbook
from your Golang application using
go-ansible
library, you must define a
AnsiblePlaybookCmd
,
AnsiblePlaybookOptions
,
AnsiblePlaybookConnectionOptions
as its shown below.

AnsiblePlaybookConnectionOptions
where is defined how to connect to hosts.
go
ansiblePlaybookConnectionOptions := &options.AnsiblePlaybookConnectionOptions{
    Connection: "local",
}

AnsiblePlaybookOptions
where is defined which should be the
ansible-playbook
execution behavior and where to find execution configuration.
go
ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{
    Inventory: "127.0.0.1,",
}

AnsiblePlaybookPrivilegeEscalationOptions
where is defined wether to become another and how to do it.
go
privilegeEscalationOptions := &options.AnsiblePlaybookPrivilegeEscalationOptions{
    Become:        true,
    BecomeMethod:  "sudo",
}

AnsiblePlaybookCmd
where is defined the command execution.
go
cmd := &playbook.AnsiblePlaybookCmd{
    Playbook:          "site.yml",
    ConnectionOptions: ansiblePlaybookConnectionOptions,
    Options:           ansiblePlaybookOptions,
    PrivilegeEscalationOptions: privilegeEscalationOptions,
}

Once the

AnsiblePlaybookCmd
is already defined it could be run it using the
Run
method. Though is not defined an Executor
DefaultExecute
is used having the default parameters
go
err := cmd.Run(context.TODO())
if err != nil {
    panic(err)
}

The result of the

ansible-playbook
execution is shown below.
 ──
 ── PLAY [all] *********************************************************************
 ──
 ── TASK [Gathering Facts] *********************************************************
 ── ok: [127.0.0.1]
 ──
 ── TASK [simple-ansibleplaybook] **************************************************
 ── ok: [127.0.0.1] => {
 ──     "msg": "Your are running 'simple-ansibleplaybook' example"
 ── }
 ──
 ── PLAY RECAP *********************************************************************
 ── 127.0.0.1                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
 ──
 ── Playbook run took 0 days, 0 hours, 0 minutes, 0 seconds

License

go-ansible is available under MIT license.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.