ansible / ansible-lint

ansible-lint checks playbooks for practices and behavior that could potentially be improved and can fix some of the most common ones for you
https://ansible.readthedocs.io/projects/lint/
GNU General Public License v3.0
3.49k stars 663 forks source link

Tags for blocks #288

Closed nmulvihill closed 7 years ago

nmulvihill commented 7 years ago

Issue Type

Ansible and Ansible Lint details

ansible --version 
   2.3.1.0
ansible-lint --version
   3.4.12

Desired Behaviour

Using the example TaskHasTag rule, I would expect that if a task is inside a block and the block is tagged, the task does not have to be.

- block:
   - name: task
      win_something:
         args: XXX
   - name: another task
      win_something
         args2: XXX

   tags: [tags,for,both,tasks]

Actual Behaviour (Bug report only)

Reports an error.

Please give some details of what is actually happening. Include a minimum complete verifiable example with:

willthames commented 7 years ago

As it's an example rule, it's relatively unsupported. It's probably a tricky one to fix too, but if someone is able to do it, I'll take a look at the fix.

nmulvihill commented 7 years ago

I have been able to create it in matchplay() but I cannot return True/False, I believe it is looking for a dictionary? Is there a way to link matchplay() with a T/F result? Here is the code to do it with matchplay:

def matchplay(self, file, play):
        no_tags = True

        for block in play["tasks"]:
            if "block" in block:
                if not ('tags' in block):
                    for task in block["block"]:
                        no_tags = no_tags and 'tags' in task
            else:
                no_tags = no_tags and 'tags' in block

        print(not no_tags)
        # return this value!!
nmulvihill commented 7 years ago

I was able to get this to work other than the exclusion list. It does not seem terribly difficult though.

from ansiblelint import AnsibleLintRule

class TaskHasTag(AnsibleLintRule):
    id = 'ANSIBLE_03'
    shortdesc = 'Tasks must have tag'
    description = 'Tasks must have tag'
    tags = ['productivity', 'tags']
    _tagless_tasks = ['meta','debug','include','include_role','set_fact','fail','setup']

    def matchplay(self, file, play):
        ret = []
        no_tags = True
        # print (play)
        if ("tasks" in play) and (play["tasks"] != None):
            for block in play["tasks"]:
                if "block" in block:
                    if not ('tags' in block):
                        for task in block["block"]:
                            no_tags = no_tags and 'tags' in task
                else:
                    no_tags = no_tags and 'tags' in block

        elif "block" in play:
            if not ('tags' in play):
                for task in play["block"]:
                    no_tags = no_tags and 'tags' in task

        if not no_tags:
            ret.append((file, self.shortdesc))
        return ret
        #TODO: Add exceptions