Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow backticks in shell commands #894

Merged
merged 1 commit into from
Jul 14, 2020
Merged

Allow backticks in shell commands #894

merged 1 commit into from
Jul 14, 2020

Conversation

turettn
Copy link
Contributor

@turettn turettn commented Jul 13, 2020

- name: create rabbitmq-admin-creds creds
  shell: kubectl --context {{ k8s_context }} \
                 -n {{ namespace }} create secret generic rabbitmq-admin-creds \
                 --from-literal=password=`openssl rand -base64 12` \
                 --from-literal=cookie=`uuidgen`
  register: rbt_secret
  changed_when: rbt_secret.rc == 0
  failed_when: rbt_secret.rc != 0 and 'AlreadyExists' not in rbt_secret.stderr

Ansible-lint did not like it:

[305] Use shell only when shell functionality is required
roles/secrets/tasks/main.yml:29
Task/Handler: create rabbitmq-admin-creds creds

I switched it to a command, and it failed because the backticks were not expanded by the shell.

This PR prevents 305 from being thrown if a backtick is present in the command. A unit test is also included.

```yaml
- name: create rabbitmq-admin-creds creds
  shell: kubectl --context {{ k8s_context }} \
                 -n {{ namespace }} create secret generic rabbitmq-admin-creds \
                 --from-literal=password=`openssl rand -base64 12` \
                 --from-literal=cookie=`uuidgen`
  register: rbt_secret
  changed_when: rbt_secret.rc == 0
  failed_when: rbt_secret.rc != 0 and 'AlreadyExists' not in rbt_secret.stderr
```

Ansible-lint did not like it:

```
[305] Use shell only when shell functionality is required
roles/secrets/tasks/main.yml:29
Task/Handler: create rabbitmq-admin-creds creds
```

I switched it to a command, and it failed because the backticks were not expanded by the shell.

This commit prevents 305 from being thrown if a backtick is present in the command.
@webknjaz
Copy link
Member

webknjaz commented Jul 13, 2020

                 --from-literal=cookie=`uuidgen`

FWIW backticks are considered deprecated in favor of $() and I'd suggest you to use

 - name: create rabbitmq-admin-creds creds
   shell: kubectl --context {{ k8s_context }} \
                  -n {{ namespace }} create secret generic rabbitmq-admin-creds \
-                 --from-literal=password=`openssl rand -base64 12` \
+                 --from-literal=password=$(openssl rand -base64 12) \
-                 --from-literal=cookie=`uuidgen`
+                 --from-literal=password=`openssl rand -base64 12` \
-                 --from-literal=cookie=$(uuidgen)
+                 --from-literal=cookie=$(uuidgen)
   register: rbt_secret
   changed_when: rbt_secret.rc == 0
   failed_when: rbt_secret.rc != 0 and 'AlreadyExists' not in rbt_secret.stderr

http://mywiki.wooledge.org/BashFAQ/082

P.S. Extra tip — it's often easier to maintain YAML blocks via | or > than try to guess the right indent for the string so I'd use the following YAML syntax for the shell command value:

- ...
  shell: >-
    kubectl --context {{ k8s_context }}
    -n {{ namespace }} create secret generic rabbitmq-admin-creds
    --from-literal=password=$(openssl rand -base64 12)
    --from-literal=cookie=$(uuidgen)

@turettn
Copy link
Contributor Author

turettn commented Jul 13, 2020

@webknjaz Thanks for your response! To get my CI chain to stop complaining in the short term, I did exactly as you suggested and swapped in $(...) instead of the backticks.

While definitely not best practice, I don't think bash ever deprecated backticks (in the sense of "knock it off, these will not be supported in a future version"). The manual doesn't say anything about them being deprecated that I can find, and still lists them on the command substitution page.

If there is a consensus that people should not be using backticks via the shell command in Ansible, could we split that into a separate check, in the spirit of ShellWithoutPipefail? That way, the implied fix (use command, not shell) will not break their code.

@webknjaz
Copy link
Member

Yeah, having a separate check sounds reasonable. I'm even thinking that maybe there should be a check that invokes some external binary like shellcheck that would do all the magic. OTOH this would probably be too heavy for the ansible-lint core.

Copy link
Member

@ssbarnea ssbarnea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with all comments. The idea to use an external shell linter would really be great. Still, I have no idea how it would be possible because we would first have to expand jinja2 blocks before sending it to the linter.

@ssbarnea ssbarnea merged commit 79c8e53 into ansible:master Jul 14, 2020
@turettn turettn deleted the backticks_in_shells branch July 14, 2020 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants