Skip to content

Commit

Permalink
Fix quotes converting free-form syntax to yaml (ansible#4319)
Browse files Browse the repository at this point in the history
YAML content has been changed to reflect that the YAML loader preserves
quotes used in YAML and to utilize the preferred_quote attribute.
  • Loading branch information
cavcrosby committed Oct 18, 2024
1 parent 716f283 commit 4eb0c75
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 3 deletions.
5 changes: 3 additions & 2 deletions examples/playbooks/transform-no-free-form.transformed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
executable: /bin/bash
changed_when: false

# prettier-ignore
- name: Example task with usage for '=' as module params
ansible.builtin.debug:
msg: "'Hello there world'"
msg: 'Hello there world'
changed_when: false

- name: Task that has a non-debug string with spaces
ansible.builtin.set_fact:
foo: '"String with spaces"'
foo: "String with spaces"
1 change: 1 addition & 0 deletions examples/playbooks/transform-no-free-form.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ansible.builtin.raw: executable=/bin/bash echo foo # <-- don't use executable=
changed_when: false

# prettier-ignore
- name: Example task with usage for '=' as module params
ansible.builtin.debug: msg='Hello there world'
changed_when: false
Expand Down
3 changes: 3 additions & 0 deletions src/ansiblelint/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ def main():
".config/ansible-lint.yaml",
]

DOUBLE_QUOTE_PLACEHOLDER = "__double__"
SINGLE_QUOTE_PLACEHOLDER = "__single__"


class States(Enum):
"""States used are used as sentinel values in various places."""
Expand Down
29 changes: 28 additions & 1 deletion src/ansiblelint/rules/no_free_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
import functools
import re
import sys
from io import StringIO
from typing import TYPE_CHECKING, Any

from ansiblelint.constants import INCLUSION_ACTION_NAMES, LINE_NUMBER_KEY
from ansiblelint.constants import (
DOUBLE_QUOTE_PLACEHOLDER,
INCLUSION_ACTION_NAMES,
LINE_NUMBER_KEY,
SINGLE_QUOTE_PLACEHOLDER,
)
from ansiblelint.rules import AnsibleLintRule, TransformMixin
from ansiblelint.rules.key_order import task_property_sorter
from ansiblelint.yaml_utils import FormattedYAML

if TYPE_CHECKING:
from ruamel.yaml.comments import CommentedMap, CommentedSeq
Expand Down Expand Up @@ -125,6 +132,26 @@ def filter_values(
quote = v[0]
_, v, remainder = v.split(quote, 2)
v = f"{quote}{v}{quote}"

preamble_comment: str | None = getattr(
data,
"preamble_comment",
None,
)
with StringIO() as stream:
if preamble_comment:
stream.write(preamble_comment)
FormattedYAML(
version=(1, 1) if lintable.is_owned_by_ansible() else None,
).dump(data, stream)

# quoting was munged by the emitter
if f" {v}" not in stream.getvalue():
if quote == '"':
placeholder = DOUBLE_QUOTE_PLACEHOLDER
else:
placeholder = SINGLE_QUOTE_PLACEHOLDER
v = v.replace(quote, placeholder)
else:
try:
v, remainder = v.split(" ", 1)
Expand Down
4 changes: 4 additions & 0 deletions src/ansiblelint/yaml_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@

from ansiblelint.constants import (
ANNOTATION_KEYS,
DOUBLE_QUOTE_PLACEHOLDER,
NESTED_TASK_KEYS,
PLAYBOOK_TASK_KEYWORDS,
SINGLE_QUOTE_PLACEHOLDER,
)
from ansiblelint.utils import Task

Expand Down Expand Up @@ -1182,6 +1184,8 @@ def _post_process_yaml(
text = text.split("\n", 1)[1]

text = text.rstrip("\n") + "\n"
text = text.replace(DOUBLE_QUOTE_PLACEHOLDER, '"')
text = text.replace(SINGLE_QUOTE_PLACEHOLDER, "'")

lines = text.splitlines(keepends=True)
full_line_comments: list[tuple[int, str]] = []
Expand Down

0 comments on commit 4eb0c75

Please sign in to comment.