Repository: ansible/ansible

Issue:
new syntax checker too agressive
##### Issue Type:

I'm getting "ERROR: Syntax Error while loading YAML script," when a tasks/main.yml file in my role doesn't start with '---', this is optional in YAML and works in previous versions.
##### Ansible Version:

ansible 1.6 (devel 5f3ea7512f)
##### Environment:

Ubuntu 12, 13 and Gentoo
##### Summary:

Over eager syntax checking 
##### Steps To Reproduce:

create a role with a tasks/main.yml w/o starting with ---
##### Expected Results:

file works w/o error
##### Actual Results:

 "ERROR: Syntax Error while loading YAML script,"



Discussion:
I have not been able to duplicate this issue.  There doesn't appear to be anything that would cause this from what I can tell.

```
ansible --version
ansible 1.6 (devel 5f3ea7512f) last updated 2014/03/08 17:39:51 (GMT -500)
```

#### role.yml

```
- hosts: all
  gather_facts: false
  roles:
    - test
```

#### roles/test/tasks/main.yml

```
- debug:
    msg: test
```

```
ansible-playbook -i localhost, -c local role.yml

PLAY [all] ********************************************************************

TASK: [test | debug ] *********************************************************
ok: [localhost] => {
    "item": "",
    "msg": "test"
}

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0
```

I tested this on Mac and Ubuntu 12.04.  On Ubuntu I tried with pyyaml from pypi and python-yaml.

weird, reverting to 1.5 makes everything work, I'll bisect when I have more
time.

Can you please provide something (like a minimal test repo) that helps us reproduce this?

There's also no new syntax checker.  If a file starts with "{" or "[" we do parse it as pure JSON now though, so to avoid lots of very _wrong_ syntax checks on an invalid JSON file.

did a quick bisect: 79799f681903141e815e4c44b035590124549f12
doesn't look like it makes much sense.

I'll try to create a simple case, I now have 3 roles throwing errors with
this and the fix is adding --- or using previous version of ansible.

I'm in middle of DC migrations so I might not get to simple case till
tomorrow.

"doesn't look like it makes much sense."

It makes a lot of sense.   if the file is JSON, running it through the YAML syntax checker code is a bad idea, so we sidestep that for JSON files.

You will see "loaded" correctly passed to yaml.safe_load in commits up the tree.

its failing on included tasks (.yml) not json or any other files, that is
why it doesn't make sense.

Still in the middle of a move, so I probably won't have time to really
debug this till Mon/Tue.

so i got a good test case:

```
mkdir -p test/roles
cd test
ansible-galaxy install briancoca.oracle7-java -p ./roles
ansible-playbook -i 'localhost,' test.yml -K
```

where test.yml is

```
- hosts: localhost
  sudo: True
  connection: local
  roles: 
    - briancoca.oracle7-java
```

this errors out with latest devel, but works fine with 1.4

```
ERROR: Syntax Error while loading YAML script, /home/bcoca/test/roles/briancoca.oracle7-java/tasks/main.yml
```

Ok, so I was figuring that is was the `data.lstrip()` somehow, but could not figure out how.  I don't think it was anticipated that the first line of the YAML file would be indented.

This indentation, causes what was the following:

```
    - name: Setup oracle java deb repo
      apt_repository: repo="ppa:webupd8team/java" update_cache=yes
      when: ansible_distribution in [ 'Ubuntu' ]
```

To end up looking like:

```
- name: Setup oracle java deb repo
      apt_repository: repo="ppa:webupd8team/java" update_cache=yes
      when: ansible_distribution in [ 'Ubuntu' ]
```

This ends up being invalid YAML at that point.  Which is why placing `---` on the first line fixes things, since it's indentation level doesn't get changed.

So I might suggest something like the following, where we check if the stripped data starts with `{` or `[` but still operate on the non-lstripped data.

``` diff
diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py
index 405641e..30814b5 100644
--- a/lib/ansible/utils/__init__.py
+++ b/lib/ansible/utils/__init__.py
@@ -354,9 +354,9 @@ def smush_ds(data):
 def parse_yaml(data, path_hint=None):
     ''' convert a yaml string to a data structure.  Also supports JSON, ssssssh!!!'''

-    data = data.lstrip()
+    stripped_data = data.lstrip()
     loaded = None
-    if data.startswith("{") or data.startswith("["):
+    if stripped_data.startswith("{") or stripped_data.startswith("["):
         # since the line starts with { or [ we can infer this is a JSON document.
         try:
             loaded = json.loads(data)
```

ah, nice catch.

Most of my role or other task include files are copy/paste from an play, so
they inherited the indentation level of the original.


Resolving patch:
diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py
--- a/lib/ansible/utils/__init__.py
+++ b/lib/ansible/utils/__init__.py
@@ -354,9 +354,9 @@ def smush_ds(data):
 def parse_yaml(data, path_hint=None):
     ''' convert a yaml string to a data structure.  Also supports JSON, ssssssh!!!'''
 
-    data = data.lstrip()
+    stripped_data = data.lstrip()
     loaded = None
-    if data.startswith("{") or data.startswith("["):
+    if stripped_data.startswith("{") or stripped_data.startswith("["):
         # since the line starts with { or [ we can infer this is a JSON document.
         try:
             loaded = json.loads(data)


Test patch: