Role patterns

Hi all,

I have started with Ansible some months ago, and as I like having a kind of patterns in order to have reusable pieces of code. I have created this sort of example role with some of them (ofc, it is not functional). The idea is having something to clone and start working … What do you think about the idea (and also, about the implementation)? https://github.com/jriguera/ansible-role-pattern

Cheers

This is very nice. An excellent guide over the ansible docs.

On the topic patterns, something I have been experiment with is to not try to define attributes for config files that are then substituted via a template by the role. Rather I have been using native configuration.

It seems to me that there is little value trying to turn every type of config into native yaml only to have to regenerate the native format. By using the native format directly the configuration is much clearer with less cognitive load due the the translation.

Here’s an example using my logstash role:

`
roles:

  • role: logstash
    logstash_configs:
    00_mesos: |
    input {
    file {
    path => [“/var/log/mesos/mesos-slave.INFO”]
    exclude => [“.log.”, “.gz"]
    tags => [“infra”, “mesos”, “mesos-slave”]
    add_field => { “level” => “INFO” }
    }
    file {
    path => [“/var/log/mesos/mesos-slave.WARN”]
    exclude => ["
    .log.", ".gz”]
    tags => [“infra”, “mesos”, “mesos-slave”]
    add_field => { “level” => “WARN” }
    }
    file {
    path => [“/var/log/mesos/mesos-slave.ERROR”]
    exclude => [“.log.”, “*.gz”]
    tags => [“infra”, “mesos”, “mesos-slave”]
    add_field => { “level” => “ERROR” }
    }
    }

00_consul: |
input {
file {
type => “consul”
path => [“/var/log/consul.log”]
exclude => [“.log.”, “*.gz”]
tags => [“consul”]
}
}

00_vimana: |
input {
file {
type => “vimana”
path => [“{{vi_log_dir}}/.log"]
exclude => ["
.log.", ".gz”]
tags => [“vimana”]
codec => json
}
}

50_env_filter: |
filter {
add_field => { “env”, “{{env}}” }
}

99_rabbitmq_output: |
output {
rabbitmq {
host => “rabbitmq.service.ops.consul”
port => {{rabbitmq_port}}
user => “{{elk_rabbitmq_logstash_user}}”
password => “{{elk_rabbitmq_logstash_password}}”
vhost => “logstash”
exchange => “logs_json”
exchange_type => “direct”
durable => true
}
}

99_debug_output: |
output {
stdout {
codec => rubydebug
}
}
`

Yep, I think that is a good pattern as well. With your permission, when I have enough time I will add that example to the repo, or you can do it by yourself if you want :slight_smile:

I used to just make them templates, keep the file in native format
and only template out the options that vary per my different
classifications (stage, location, purpose). Where stage was
devel/qa/staging/prod, location had to do with datacenter or network
(ntp, routes, dns servers, gateways) and purpose was the function the
machine was dedicated for (could be multiple, but mostly webapp, load
balancer, db, infrastructure, etc).

I have found (in my very short time with ansible, but informed by years of creating
templates in chef) that all the context I need is already abstracted in the playbook,
so creating the configuration directly in the play (with substitution) and passing the
final config to the role yields the most flexibility. By that I mean the role did not have
decide up front what bits the config I might and and might want to parameterize. Also,
some configs are soooo big, with so much optional stuff it seems best to leave declaring
the config to the playbook.

Either way is fine by me.