Problem with parameterizing role

I have a group of hosts that have two tomcat instances on them, and I need the server.xml to have different values in each instance. Initially, I tried to write a jinja2 loop into a template, which I bailed on when someone in the IRC channel pointed out parameterizing the role (from http://docs.ansible.com/ansible/playbooks_roles.html - there’s not a direct anchor, so I’ll quote):

Also, should you wish to parameterize roles, by adding variables, you can do so, like this:

  • hosts: webservers
    roles:
  • common
  • { role: foo_app_instance, dir: ‘/opt/a’, port: 5000 }
  • { role: foo_app_instance, dir: ‘/opt/b’, port: 5001 }

But when I try the above, both server.xml’s end up with the same value. It looks like each subsequent pass through the role puts it’s value in both directories, so after the second time it runs, both server.xml’s have the second value. I pastebinned my playbook, role, and the line from the template: http://pastebin.com/eDMQkY3H

If anybody could help me with this, or tell me what I’m doing wrong, I’d greatly appreciate it.

You forgot to include condition in the tasks, like for example:

  • name: Template to 1st server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_1/conf/server.xml owner=tomcat7 group=nogroup mode=0600
    when: port == “5000”

  • name: Template to 2nd server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_2/conf/server.xml owner=tomcat7 group=nogroup mode=0600
    when: port == “5001”

otherwise each will get executed on each run, of course.

Don’t you just need one task in your role which takes the dir variable? Something like:

template: src=server.xml.j2 dest={{dir}}/server.xml owner=tomcat7 group=nogroup mode=0600

Thanks, Igor, I’ll give that a try. I thought it might have something to do with how the task was set up, but since there was no example given for that, I was just guessing, grasping at straws.

I’m not sure that addresses having the two, separate server.xml files sent to different directories. Is dir a “reserved” variable?

You’re executing the role twice, each time with different parameters. If the role writes a single file each time, you end up with two files. The way you’ve got it now, the role will write both files each time it’s executed; the result is what you’re seeing: both files have the same content, which comes from the second call to the role.

Ok, so what you’re telling me is the documentation is wrong? Because that’s literally exactly what it’s saying to do - if you look at my original post, you’ll see I quoted what the documentation says to do.

I’m not saying it’s right and you’re wrong. If it’s wrong, that’s what I want to hear.

Thank you,

Roger Sherman
public key - A3068658

Roger, the documentation you are quoting is perfectly fine, it shows you how to invoke the same role with different parameters. What you are then doing inside the role is wrong. It is two different things right?

You need to understand how playbooks and roles work in Ansible and Paul’s comment is doing a good job to help you. Read it again carefully.

I’ve read it quite carefully. For whatever reason, I’m not understanding what he’s saying.

Thanks for the help, though.

Thank you,

Roger Sherman
public key - A3068658

Hi Roger,

I don’t know how much programming experience you have, but you can think of the role as a subroutine. With the syntax you’ve got, you’re calling this role/subroutine twice, therefore it’s going to do each task in the role twice. However, you only want it to do one thing on each call, which is to create a file in the directory specified with the ‘dir’ parameter, having the contents of the port you’ve specified.

Can I suggest that you try writing the role to have one task as I posted it and see if it does what you want.

Not sure if this will make it clearer or muddier, here’s the flow of you code. The playbook is in red, the resulting tasks executed are in blue.

What’s you’re currently doing:

  • { role: tomcat7, dir: ‘/var/opt/tomcat_1/conf’, server_port: 8105 }

  • name: Template to 1st server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_1/conf/server.xml owner=tomcat7 group=nogroup mode=0600

  • name: Template to 2nd server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_2/conf/server.xml owner=tomcat7 group=nogroup mode=0600

  • { role: tomcat7, dir: ‘/var/opt/tomcat_2/conf’, server_port: 8205 }

  • name: Template to 1st server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_1/conf/server.xml owner=tomcat7 group=nogroup mode=0600

  • name: Template to 2nd server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_2/conf/server.xml owner=tomcat7 group=nogroup mode=0600

What my suggestion will do:

  • { role: tomcat7, dir: ‘/var/opt/tomcat_1/conf’, server_port: 8105 }

  • name: Template to server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_1/conf/server.xml owner=tomcat7 group=nogroup mode=0600

  • { role: tomcat7, dir: ‘/var/opt/tomcat_2/conf’, server_port: 8205 }

  • name: Template to server.xml
    template: src=server.xml.j2 dest=/var/opt/tomcat_2/conf/server.xml owner=tomcat7 group=nogroup mode=0600

That does make it clearer, Paul, thank you.

Apologies for the delayed response, life intervened for a moment.

Thank you,

Roger Sherman
public key - A3068658