Repository: ansible/ansible-lint

Issue:
False positive [E602] Don't compare to empty string
# Issue Type
- Bug report

# Ansible and Ansible Lint details

```
ansible --version
2.5.7
ansible-lint --version
4.0.0
```

- ansible installation method: pip
- ansible-lint installation method: pip

# Desired Behaviour

No false positive errors

# Actual Behaviour (Bug report only)

    [E602] Don't compare to empty string

See https://github.com/openstack/tripleo-quickstart/blob/master/roles/tripleo-inventory/tasks/openstack.yml#L60

I found 4 similar places where bit more complex jinja2 syntax triggers this bug which is weird as there is no conditional involved here.

Any idea on how to avoid this until it is fixed?


Discussion:
So I just came here to note that I am not sure what to do instead of comparing to an empty string, since the language doesn't support strict types and this is the only way to check if a string is 'empty' or 'not empty'.

For example, with Ansible 2.7.x, if I set `my_var: 'testing'` and have the following task:

```
- name: Do something with my_var.
  command: "do_something_with {{ my_var }}"
  when: my_var
```

Then I get the error:

```
fatal: [localhost]: FAILED! =>
The conditional check 'my_var' failed. The error was: error while evaluating conditional (my_var): 'testing' is undefined
```

If I set it like:

```
- name: Do something with my_var.
  command: "do_something_with {{ my_var }}"
  when: my_var != ''
```

Then I have no problem, and it is more correct IMO.

So basically, if that's wrong... what's the right way to do that kind of check? I am scratching my head and I use this pattern fairly often.
Same problem for me - using conditional check as ansible-lint (and ansible-galaxy) wants the playbook exits with an error. 
Using the example from Jeff Geerling above - my_var is set to `'/var/run/myapp.pid'` . When task is run with conditional `when: my_var` ansible exits with error:

```
fatal: [instance]: FAILED! => {"msg": "The conditional check 'my_var' failed. 
The error was: template error while templating string: unexpected '/'. 
String: {% if /var/run/myapp.pid %} True {% else %} False {% endif %}\n\nThe error appears
to have been in '/bla/blub.yml': line 14, column 3, but may\nbe elsewhere in the file 
depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- 
name: \"Do something with my_var\"\n  ^ here\n"}
```

How do we check if `when: my_var != ''` is not allowed?

Resolving patch:
diff --git a/lib/ansiblelint/rules/ComparisonToEmptyStringRule.py b/lib/ansiblelint/rules/ComparisonToEmptyStringRule.py
--- a/lib/ansiblelint/rules/ComparisonToEmptyStringRule.py
+++ b/lib/ansiblelint/rules/ComparisonToEmptyStringRule.py
@@ -16,7 +16,7 @@ class ComparisonToEmptyStringRule(AnsibleLintRule):
     tags = ['idiom']
     version_added = 'v4.0.0'
 
-    empty_string_compare = re.compile("[=!]= ?[\"'][\"']")
+    empty_string_compare = re.compile("[=!]= ?(\"{2}|'{2})")
 
     def match(self, file, line):
         return self.empty_string_compare.search(line)


Test patch:
diff --git a/test/TestComparisonToEmptyString.py b/test/TestComparisonToEmptyString.py
--- a/test/TestComparisonToEmptyString.py
+++ b/test/TestComparisonToEmptyString.py
@@ -5,24 +5,21 @@
     ComparisonToEmptyStringRule)
 from test import RunFromText
 
-PASS_WHEN = '''
+SUCCESS_TASKS = '''
 - name: shut down
   command: /sbin/shutdown -t now
   when: ansible_os_family
 '''
 
-FAIL_IS_EMPTY = '''
+FAIL_TASKS = '''
 - hosts: all
   tasks:
   - name: shut down
     command: /sbin/shutdown -t now
     when: ansible_os_family == ""
-'''
-
-FAIL_IS_NOT_EMPTY = '''
-- name: shut down
-  command: /sbin/shutdown -t now
-  when: ansible_os_family != ""
+  - name: shut down
+    command: /sbin/shutdown -t now
+    when: ansible_os_family !=""
 '''
 
 
@@ -33,14 +30,10 @@ class TestComparisonToEmptyStringRule(unittest.TestCase):
     def setUp(self):
         self.runner = RunFromText(self.collection)
 
-    def test_compare_when(self):
-        results = self.runner.run_role_tasks_main(PASS_WHEN)
+    def test_success(self):
+        results = self.runner.run_role_tasks_main(SUCCESS_TASKS)
         self.assertEqual(0, len(results))
 
-    def test_compare_is_empty(self):
-        results = self.runner.run_playbook(FAIL_IS_EMPTY)
-        self.assertEqual(1, len(results))
-
-    def test_compare_is_not_empty(self):
-        results = self.runner.run_role_tasks_main(FAIL_IS_NOT_EMPTY)
-        self.assertEqual(1, len(results))
+    def test_fail(self):
+        results = self.runner.run_playbook(FAIL_TASKS)
+        self.assertEqual(2, len(results))