243

Is there a way to only run one task in ansible playbook?

For example, in roles/hadoop_primary/tasks/hadoop_master.yml. I have "start hadoop job tracker services" task. Can I just run that one task?

hadoop_master.yml file:

# Playbook for  Hadoop master servers

- name: Install the namenode and jobtracker packages
  apt: name={{item}} force=yes state=latest
  with_items: 
   - hadoop-0.20-mapreduce-jobtracker
   - hadoop-hdfs-namenode
   - hadoop-doc
   - hue-plugins

- name: start hadoop jobtracker services
  service: name=hadoop-0.20-mapreduce-jobtracker state=started
  tags:
   debug
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Billz
  • 7,879
  • 7
  • 33
  • 35

7 Answers7

356

You should use tags: as documented in https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html


If you have a large playbook it may become useful to be able to run a specific part of the configuration without running the whole playbook.

Both plays and tasks support a “tags:” attribute for this reason.

Example:

tasks:

    - yum: name={{ item }} state=installed
      with_items:
         - httpd
         - memcached
      tags:
         - packages

    - template: src=templates/src.j2 dest=/etc/foo.conf
      tags:
         - configuration

If you wanted to just run the “configuration” and “packages” part of a very long playbook, you could do this:

ansible-playbook example.yml --tags "configuration,packages"

On the other hand, if you want to run a playbook without certain tasks, you could do this:

ansible-playbook example.yml --skip-tags "notification"

You may also apply tags to roles:

roles:
  - { role: webserver, port: 5000, tags: [ 'web', 'foo' ] }

And you may also tag basic include statements:

- include: foo.yml tags=web,foo

Both of these have the function of tagging every single task inside the include statement.

Patrick Decat
  • 618
  • 5
  • 11
Mxx
  • 8,979
  • 4
  • 27
  • 37
  • Have a look at this answer: https://stackoverflow.com/a/52888274/2834918. The accepted answer here pops up at google and duckduckgo quite at the top but hides the newer interface introduced with ansible 2.7. – bixel Jan 20 '20 at 15:58
  • 6
    I'd recommend against using `--tags`. The problem is that `ansible-playbook` will not fail if you typoed the tag, and from what I've been told on IRC there's no way to make it fail. This means it's easy to introduce hard-to-find bugs during refactoring a playbook. I personally decided instead to go split a playbook to smaller ones, so `ansible-playbook` would run everything inside a given one. Not something I like, but oh well… – Hi-Angel Aug 19 '20 at 12:51
  • 2
    "from what i've been told on irc" is hardly a quality reference source. Perhaps you want to link to some published article or post discussing those issues? – Mxx Aug 19 '20 at 18:09
  • 1
    @Mxx sure, is docs considered a quality source? In this case just type `man ansible-playbook` and make a search for "tags" keyword. You'll only find options chose/skip/list tags. No option to make it fail. – Hi-Angel Aug 20 '20 at 06:11
  • @Hi-Angel, my answer above links to the official documentation page. – Mxx Aug 20 '20 at 14:58
  • 1
    This is not flexible and selective enough. Also, when tasks depends on each other it does not work. – Federico Feb 21 '21 at 19:45
  • 1
    @Federico, please post a better answer. – Mxx Feb 21 '21 at 23:33
  • The answer from Victor Ashik is readable below since 2015 – Federico Feb 22 '21 at 12:12
  • 1
    There is nothing wrong with using tags. If you want to know what tags a playbook has, you can with `ansible-playbook playbook.yml --list-tags` – slf Sep 16 '21 at 16:14
127

There is a way, although not very elegant:

  1. ansible-playbook roles/hadoop_primary/tasks/hadoop_master.yml --step --start-at-task='start hadoop jobtracker services'
  2. You will get a prompt: Perform task: start hadoop jobtracker services (y/n/c)
  3. Answer y
  4. You will get a next prompt, press Ctrl-C
Victor Ashik
  • 1,389
  • 1
  • 8
  • 4
  • 7
    Combining that with the `--check` and `-vvv` option is also quite useful. It will not actually perform the command but give you very verbose output what would have happened. – lanoxx Jan 24 '19 at 16:19
17

FWIW with Ansible 2.2 one can use include_role:

playbook test.yml:

- name: test
  hosts:
    - 127.0.0.1
  connection: local
  tasks:
    - include_role:
        name: test
        tasks_from: other

then in roles/test/tasks/other.yml:

- name: say something else
  shell: echo "I'm the other guy"

And invoke the playbook with: ansible-playbook test.yml to get:

TASK [test : say something else] *************
changed: [127.0.0.1]
Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
ddragosd
  • 226
  • 2
  • 3
10

See my answer here: Run only one task and handler from ansible playbook

It is possible to run separate role (from roles/ dir):

ansible -i stage.yml -m include_role -a name=create-os-user localhost

and separate task file:

ansible -i stage.yml -m include_tasks -a file=tasks/create-os-user.yml localhost

If you externalize tasks from role to root tasks/ directory (reuse is achieved by import_tasks: ../../../tasks/create-os-user.yml) you can run it independently from playbook/role.

gavenkoa
  • 45,285
  • 19
  • 251
  • 303
8

I would love the ability to use a role as a collection of tasks such that, in my playbook, I can choose which subset of tasks to run. Unfortunately, the playbook can only load them all in and then you have to use the --tags option on the cmdline to choose which tasks to run. The problem with this is that all of the tasks will run unless you remember to set --tags or --skip-tags.

I have set up some tasks, however, with a when: clause that will only fire if a var is set.

e.g.

# role/stuff/tasks/main.yml
- name: do stuff
  when: stuff|default(false)

Now, this task will not fire by default, but only if I set the stuff=true

$ ansible-playbook -e '{"stuff":true}'

or in a playbook:

roles:
- {"role":"stuff", "stuff":true}
ChePazzo
  • 181
  • 2
  • 3
  • I'm just a newbie, and I hear what you're saying... but I would explore why you are averse to having the whole playbook run. A proper Ansible play is usually idempotent, and will gather facts and "do nothing" if the state criteria is met. I admit I share this concern as most of my plays "do something" rather than "check if this is the state, and do something if needed". The former could only be run once, or supervised while the latter could be run at any time and it'll be harmless. – Scott Prive Apr 30 '19 at 15:26
  • 1
    I normally use this for debug tasks. Normally, I don't want the debug info to run, but sometimes I do. Looking at the other responses, though, there might be a better way to do that now. – ChePazzo May 01 '19 at 16:54
  • Yes, there is. To be specific, one way to selectively run plays now is by "tagging" the plays. There may be OTHER ways to limit the plays also; I am still learning... – Scott Prive May 02 '19 at 01:55
  • At least in my case, the reason to not run the entire playbook is because it 1) is very long and 2) might be running against about 400 hosts. That takes a while. I make liberal use of `-t`, `-l`, and `--start-at-task` because sometimes I need to get something out fast, or I just don't feel like watching my terminal scroll for an hour. – pyansharp Apr 08 '21 at 20:03
4

are you familiar with handlers? I think it's what you are looking for. Move the restart from hadoop_master.yml to roles/hadoop_primary/handlers/main.yml:

- name: start hadoop jobtracker services
  service: name=hadoop-0.20-mapreduce-jobtracker state=started

and now call use notify in hadoop_master.yml:

- name: Install the namenode and jobtracker packages
  apt: name={{item}} force=yes state=latest
  with_items: 
   - hadoop-0.20-mapreduce-jobtracker
   - hadoop-hdfs-namenode
   - hadoop-doc
   - hue-plugins
  notify: start hadoop jobtracker services
tedder42
  • 23,519
  • 13
  • 86
  • 102
4

This can be easily done using the tags

The example of tags is defined below:

---
hosts: localhost
tasks:
 - name: Creating s3Bucket
   s3_bucket:
        name: ansiblebucket1234567890
   tags: 
       - createbucket

 - name: Simple PUT operation
   aws_s3:
       bucket: ansiblebucket1234567890
       object: /my/desired/key.txt
       src: /etc/ansible/myfile.txt
       mode: put
   tags:
      - putfile

 - name: Create an empty bucket
   aws_s3:
       bucket: ansiblebucket12345678901234
       mode: create
       permission: private
   tags:
       - emptybucket

to execute the tags we use the command

ansible-playbook creates3bucket.yml --tags "createbucket,putfile"
Nitesh Jain
  • 167
  • 1
  • 3