amazon-ec2ansibleinventory

Run ansible playbook on specific EC2


I would like to run a playbook on a specific ec2 instance by providing the instance id in command line. Something like: ansible-playbook playbook.yml -e "instance-id=i-123456".

I tried to use amazon.aws.aws_ec2 plugin inventory, but the filters does not support Jinja2 so it do not recognize the parameters provided from the command line.

Here is the inventory that I use:

plugin: amazon.aws.aws_ec2
regions:
  - us-east-2
filters:
  "tag:MyTag": "*"
hostnames:
  - instance-id

Solution

  • I would like to run a playbook on a specific ec2 instance by providing the instance id in command line.

    Ansible has --limit/-l CLI flag for that:

    playbook.yml --limit "i-123456"
    

    --limit hostname will work. It feels a little bit unsafe tho. I would like to run the playbook only on one instance at the time. If I will provide the inventory with all of the instances, but if by mistake I will forget to add the --limit flag, the playbook will run on all of the instances with the MyTag tag. Is there any better way?

    Sure. But it's important to distinct running the playbook against one host at a time from forgetting to pass the --limit flag, because the latter allows to specify as many hosts/groups as you want.

    To restrict the execution to one host at a time, you can use the serial play keyword:

    ---
    - name: Run the play on one host at a time
      hosts: all
      serial: 1
      tasks:
        - name: Show how many hosts are in the batch
          debug:
            msg: |
              List of active hosts in the current play run limited by the serial, aka ‘batch’: {{ ansible_play_batch }}
              List of hosts in the current play run, not limited by the serial: {{ ansible_play_hosts }}
              List of all the hosts that were targeted by the play: {{ ansible_play_hosts_all }}
    

    You might want to consider other options, too, see Controlling playbook execution: strategies and more.

    Now, returning to your intention to check the limits - Ansible has another special variable, ansible_limit. And here's where the difference shows up.

    If under no circumstances the playbook should proceed if ansible_limit is not set, you can assert its existence:

    ---
    - name: Check the limits
      hosts: all
      pre_tasks:
        name: Check that the limit is set
        assert:
          that: ansible_limit is defined and ansible_limit
        run_once: true
    
    # further plays
    

    Combining this with the previous snippet will allow you to ensure both conditions you were asking for.

    Additionally, if you want to run the playbook only on one single host with no chance to affect others, check the length of the limit:

    ---
    - name: Check the limits
      hosts: all
      pre_tasks:
        name: Check that the limit is set
        assert:
          that:
            - ansible_limit is defined and ansible_limit
            - ansible_limit | length == 1
        run_once: true
    
    # further plays