internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: ansible/ansible

Issue:
Missing/problematic support for su_pass in ssh.py
The following use of ansible-playbook with remote "su"-ing to root:

```
 ansible-playbook --su --ask-su-pass all mybook.yaml
```

Fails when we use the default ssh transport (and hence `ssh.py`) but succeeds when we use use the `transport = paramiko` connection driver.

The failure in the ssh driver occurred at this line:
- https://github.com/ansible/ansible/blob/release1.8.2/lib/ansible/runner/connection_plugins/ssh.py#L338

since the `self.runner.sudo_pass` variable is `None`. It makes sense that it is `None` since we aren't using sudo, but not sure why we ended up at this line in the first place. It appears that `utils.su_prompts.check_su_prompt(sudo_output)` does not evaluate to true so we end up in a sudo-specific loop.  

This code is quite complicated; it may make sense to break out "su"-related action into a separate block for maintainability reasons.



Discussion:
It looks like there is just some additional logic that needs to happen in that if statement to send the correct password perhaps similar to what is on line 351.

That specific loop is checking for the content in stderr.  We are overloading the meaning of the word "sudo" in various variables there since su was added.

Right, and I suspect that the "overloading" makes the code harder to maintain, and hence error prone.

I also suspect that not that many people use su anymore, so this may be a backwater of ansible development. Our use case: we are using ansible to bring hosts into compliance (ssh pubkey + passwordless sudo), so just need to get hosts bootstrapped, and we won't touch su again.

The su use is actually pretty high.


Resolving patch:
diff --git a/lib/ansible/runner/connection_plugins/ssh.py b/lib/ansible/runner/connection_plugins/ssh.py
--- a/lib/ansible/runner/connection_plugins/ssh.py
+++ b/lib/ansible/runner/connection_plugins/ssh.py
@@ -335,7 +335,7 @@ def exec_command(self, cmd, tmp_path, sudo_user=None, sudoable=False, executable
                         "sudo", "Sorry, try again.")
                     if sudo_errput.strip().endswith("%s%s" % (prompt, incorrect_password)):
                         raise errors.AnsibleError('Incorrect sudo password')
-                    elif sudo_errput.endswith(prompt):
+                    elif prompt and sudo_errput.endswith(prompt):
                         stdin.write(self.runner.sudo_pass + '\n')
 
                 if p.stdout in rfd:


Test patch:
Repository: ansible/ansible

Issue:
--ask-vault-pass seems to be broken
Issue Type: Bug Report
Ansible Version: ansible 1.9 (devel 2da35a55a5)
Environment:
     Ansible host: ubuntu 14.04.1
     client hosts: ubuntu, debian, and raspbarian

Summary:
      Normally I run a quick playbook I wrote to upgrade my hosts, with an encrypted vault file holding their sudo passwords:
             ansible-playbook apt_upgrade.yaml --ask-vault-pass
      This quick working when I did a git pull this morning. So I picked a revision that was definitely old than my last pull (happened to pick fd987f5395) I didn't have time to do a bisect this morning, but will plan to do so as soon as I have  chance (unless of course someone fixes it before I get that chance)

Steps To Reproduce:
     Have an encrypted vault.  Have playbook that uses that encrypted vault. Run playbook with --ask-vault-pass and it fails whether you type the right password or not.  Gives a stack trace, unfortunately I can't copy it from the terminal I am using on andriod. But the lines are:
  ansible/bin/ansible 208
  ansible/bin/ansible 117
  ansible/lib/ansible/utils/**init**.py 1130 global  name 'vault_pass'  is not defined

   I can just run:
      ansible host --ask-vault-pass
   and get the error as well.  Though in that case when it works nothing happens since no action was specified (also still exits with 1, so a little will take a little more work if I was to automate a bissect)

Expected Results:
    Should run playbook using encrypted sudo in the vault

Actual Results:
    Errors out with a stack trace.



Discussion:

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
@@ -1132,7 +1132,7 @@ def ask_passwords(ask_pass=False, ask_sudo_pass=False, ask_su_pass=False, ask_va
     if ask_vault_pass:
         vaultpass = getpass.getpass(prompt="Vault password: ")
         if vaultpass:
-            vaultpass = to_bytes(vault_pass, errors='strict', nonstring='simplerepr').strip()
+            vaultpass = to_bytes(vaultpass, errors='strict', nonstring='simplerepr').strip()
 
     return (sshpass, sudopass, supass, vaultpass)
 


Test patch:
Repository: ansible/ansible

Issue:
wrong umask calculation in AnsibleModule.atomic_move
The correct permission for a new file are calculated using `0666 ^ umask`. While xor yields the correct result for the most common umask (022) it is incorrect. For example a umask of 077 should create files with 600 permissions, but ansible creates them with 611 (0666 ^ 0077).

The correct calculation is `0666 & ~umask`



Discussion:

Resolving patch:
diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py
--- a/lib/ansible/module_utils/basic.py
+++ b/lib/ansible/module_utils/basic.py
@@ -1391,7 +1391,7 @@ def atomic_move(self, src, dest):
             # based on the current value of umask
             umask = os.umask(0)
             os.umask(umask)
-            os.chmod(dest, 0666 ^ umask)
+            os.chmod(dest, 0666 & ~umask)
             if switched_user:
                 os.chown(dest, os.getuid(), os.getgid())
 


Test patch:
Repository: ansible/ansible

Issue:
Provide host UUID in Ansible facts
Ansible should provide a consistent machine ID (UUID) in facts, if available. Sources of consistent UUIDs are, according to [machine-id](http://man7.org/linux/man-pages/man5/machine-id.5.html) manpage:
- `/etc/machine-id`
- `/var/lib/dbus/machine-id`

If these aren't available on a system, as an alternative, Ansible could provide a random UUID in a separate fact, depending on presence of `uuidgen` utility on Ansible Controller host. Then user could grab that randomly generated UUID and save it in local Ansible facts for later consistent use, for example:

```
var_uuid: '{{ ansible_local.root.uuid | default(ansible_machine_id | default(ansible_random_uuid)) }}'
```

UUID can be used to identify a host uniquely for accounting, tracking virtual machines or containers across systems, etc.



Discussion:
I'm fine with pulling existing uuid, but would not want to create and track our own as there can be divergence when not forcing the use of a  centralized data store (which currently ansible does not require). I would leave that for other tools.

I am looking into implementing this. I am new to this project, so please pardon any silly question. Can you tell me where should we put this pulled UUID? I mean what should we nest it under?

@mihirvj I think something like `ansible_machine_id` for the `/etc/machine-id` / `/var/lib/dbus/machine-id` contents.

Added to commit #10235 

@mihirvj You should probably post that in a separate PR.


Resolving patch:
diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py
--- a/lib/ansible/module_utils/facts.py
+++ b/lib/ansible/module_utils/facts.py
@@ -387,7 +387,10 @@ def get_distribution_facts(self):
                                 break
                     else:
                         self.facts['distribution'] = name
-
+        machine_id = get_file_content("/var/lib/dbus/machine-id") or get_file_content("/etc/machine-id")
+        if machine_id:
+            machine_id = machine_id.split('\n')[0]
+            self.facts["machine_id"] = machine_id
         self.facts['os_family'] = self.facts['distribution']
         if self.facts['distribution'] in OS_FAMILY:
             self.facts['os_family'] = OS_FAMILY[self.facts['distribution']]


Test patch:
Repository: ansible/ansible

Issue:
Respect global settings when merging hashes
This patch improving a condition in the `merge_hash` function to respect the global settings for merging hashes. It allows to merge hashes only if the `hash_behaviour` is set to `merge` in `ansible.cfg`.



Discussion:

Resolving patch:
diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -115,8 +115,8 @@ def __init__(self, playbook, ds, basedir, vault_password=None):
         _tasks    = ds.pop('tasks', [])
         _handlers = ds.pop('handlers', [])
 
-        temp_vars = utils.merge_hash(self.vars, self.vars_file_vars)
-        temp_vars = utils.merge_hash(temp_vars, self.playbook.extra_vars)
+        temp_vars = utils.combine_vars(self.vars, self.vars_file_vars)
+        temp_vars = utils.combine_vars(temp_vars, self.playbook.extra_vars)
 
         ds = template(basedir, ds, temp_vars)
         ds['tasks'] = _tasks
@@ -632,9 +632,9 @@ def _load_tasks(self, tasks, vars=None, role_params=None, default_vars=None, sud
                     dirname = os.path.dirname(original_file)
 
                 # temp vars are used here to avoid trampling on the existing vars structures
-                temp_vars = utils.merge_hash(self.vars, self.vars_file_vars)
-                temp_vars = utils.merge_hash(temp_vars, mv)
-                temp_vars = utils.merge_hash(temp_vars, self.playbook.extra_vars)
+                temp_vars = utils.combine_vars(self.vars, self.vars_file_vars)
+                temp_vars = utils.combine_vars(temp_vars, mv)
+                temp_vars = utils.combine_vars(temp_vars, self.playbook.extra_vars)
                 include_file = template(dirname, tokens[0], temp_vars)
                 include_filename = utils.path_dwim(dirname, include_file)
 
diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py
--- a/lib/ansible/runner/__init__.py
+++ b/lib/ansible/runner/__init__.py
@@ -674,11 +674,11 @@ def _executor_internal(self, host, new_stdin):
         # Then we selectively merge some variable dictionaries down to a
         # single dictionary, used to template the HostVars for this host
         temp_vars = self.inventory.get_variables(host, vault_password=self.vault_pass)
-        temp_vars = utils.merge_hash(temp_vars, inject['combined_cache'])
-        temp_vars = utils.merge_hash(temp_vars, self.play_vars)
-        temp_vars = utils.merge_hash(temp_vars, self.play_file_vars)
-        temp_vars = utils.merge_hash(temp_vars, self.extra_vars)
-        temp_vars = utils.merge_hash(temp_vars, {'groups': inject['groups']})
+        temp_vars = utils.combine_vars(temp_vars, inject['combined_cache'] )
+        temp_vars = utils.combine_vars(temp_vars, {'groups': inject['groups']})
+        temp_vars = utils.combine_vars(temp_vars, self.play_vars)
+        temp_vars = utils.combine_vars(temp_vars, self.play_file_vars)
+        temp_vars = utils.combine_vars(temp_vars, self.extra_vars)
 
         hostvars = HostVars(temp_vars, self.inventory, vault_password=self.vault_pass)
 


Test patch:
Repository: ansible/ansible

Issue:
Explicit package_dir in setup.py considered harmful
Consider this [command sequence to install the release candidate](https://github.com/jhermann/jhermann.github.io/wiki/Ansible#installing-a-pre-release-version).
When I don't do the `setup.py` fix, I get the import error (see below), else I don't.
Any reason you have the version with the explicit package name?

``` sh
$ ansible --version
Traceback (most recent call last):
  File "…/.venv/ansible/bin/ansible", line 7, in <module>
    execfile(__file__)
  File "…/bin/ansible", line 36, in <module>
    from ansible.runner import Runner
ImportError: No module named ansible.runner
$ sed -i~ -r -e "s~'ansible': 'lib/ansible'~'': 'lib'~" setup.py
$ python setup.py develop -U
…
$ ansible --version
ansible 1.9.0 (detached HEAD bce4bb2ce2) last updated 2015/03/11 23:41:25 (GMT +200)
…
```

Also, a `test-requirements.txt` for `pip` would be helpful. If you agree, I can do a PR for both.



Discussion:
Change to setup.py Looks good.  I'll merge a PR for that.

test-requirements.txt I think would be good but let me CC: @jlaska to make sure that won't step on anything that he's planning.


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@
       url='http://ansible.com/',
       license='GPLv3',
       install_requires=['paramiko', 'jinja2', "PyYAML", 'setuptools', 'pycrypto >= 2.6'],
-      package_dir={ 'ansible': 'lib/ansible' },
+      package_dir={ '': 'lib' },
       packages=find_packages('lib'),
       package_data={
          '': ['module_utils/*.ps1', 'modules/core/windows/*.ps1', 'modules/extras/windows/*.ps1'],


Test patch:
Repository: ansible/ansible

Issue:
ansible_distribution fact populates as "RedHat" on Oracle Linux systems
`ansible oracle_linux_os_instance -m setup -a 'filter=ansible_distribution'` will return:  
`oracle_linux_os_instance | success >> {`
`"ansible_facts": {`
`"ansible_distribution": "RedHat"`
`},`
`"changed": false`
`}`

ansible_lsb.id seems to populate properly on these systems.

/etc/redhat-release on said system is being populated _by Oracle_ as:
`Red Hat Enterprise Linux Server release 6.5 (Santiago)`



Discussion:
As discussed in IRC this is caused by Oracle having a package that 'lies' and pretends to be redhat. Still we need to deal with it and correctly detect what the system is and it looks like checking for lsb data first is the solution.


Resolving patch:
diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py
--- a/lib/ansible/module_utils/facts.py
+++ b/lib/ansible/module_utils/facts.py
@@ -87,7 +87,8 @@ class Facts(object):
     _I386RE = re.compile(r'i([3456]86|86pc)')
     # For the most part, we assume that platform.dist() will tell the truth.
     # This is the fallback to handle unknowns or exceptions
-    OSDIST_LIST = ( ('/etc/redhat-release', 'RedHat'),
+    OSDIST_LIST = ( ('/etc/oracle-release', 'Oracle Linux'),
+                    ('/etc/redhat-release', 'RedHat'),
                     ('/etc/vmware-release', 'VMwareESX'),
                     ('/etc/openwrt_release', 'OpenWrt'),
                     ('/etc/system-release', 'OtherLinux'),
@@ -287,6 +288,13 @@ def get_distribution_facts(self):
                             # Once we determine the value is one of these distros
                             # we trust the values are always correct
                             break
+                        elif name == 'Oracle Linux':
+                            data = get_file_content(path)
+                            if 'Oracle Linux' in data:
+                                self.facts['distribution'] = name
+                            else:
+                                self.facts['distribution'] = data.split()[0]
+                            break
                         elif name == 'RedHat':
                             data = get_file_content(path)
                             if 'Red Hat' in data:


Test patch:
Repository: ansible/ansible

Issue:
Internal system is interpreting the password has being a template
**Issue Type:** Bug Report

**Ansible Version:**

```
❯ ansible --version
ansible 1.8.4
  configured module search path = None
```

**Environment:**
- Host: 

```
❯ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.10.2
BuildVersion:   14C1510
```
- Managed OS: N/A

**Steps To Reproduce:**

```
ansible-playbook -i _provision/inventory _provision/common.yml --ask-vault-pass --ask-sudo-pass
```

When asked for the sudo password, insert the following: `Gr[Y+JBp.8i92M)9{%D{y<9xZ` (this password has been revoked). The role common.yml itself is irrelevant, but it asks for sudo by starting with:

```

---

- hosts: staging
  sudo: yes
```

**Expected Results:**
It should start running the playbook on the remote machine

**Actual Results:**

```
❯ ansible-playbook -i _provision/inventory _provision/common.yml --ask-vault-pass --ask-sudo-pass -vvvv
sudo password:
Vault password:

PLAY [staging] ****************************************************************

GATHERING FACTS ***************************************************************
fatal: [REDACTED IP] => template error while templating string: Encountered unknown tag 'D'.

TASK: [common | Update apt cache] *********************************************
FATAL: no hosts matched or all hosts have already failed -- aborting


PLAY RECAP ********************************************************************
           to retry, use: --limit @/Users/couto/common.retry

[REDACTED IP]              : ok=0    changed=0    unreachable=1    failed=0
```

It seems to me, that the above password is being interpreted by the internal template system, since by chance the password contains the `{%` chars.



Discussion:
It seems that the workaround is running `ansible-playbook` while being within the root environment.

I experienced this bug on a fresh Ubuntu 14.04 AWS instance when I went to utilize @zach-adams' hgv-deploy-full Ansible Playbook. A sheepish `sudo su` beforehand allowed everything to complete successfully.


Resolving patch:
diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py
--- a/lib/ansible/runner/__init__.py
+++ b/lib/ansible/runner/__init__.py
@@ -934,8 +934,12 @@ def _executor_internal_inner(self, host, module_name, module_args, inject, port,
 
         # user/pass may still contain variables at this stage
         actual_user = template.template(self.basedir, actual_user, inject)
-        actual_pass = template.template(self.basedir, actual_pass, inject)
-        self.become_pass = template.template(self.basedir, self.become_pass, inject)
+        try:
+            actual_pass = template.template(self.basedir, actual_pass, inject)
+            self.become_pass = template.template(self.basedir, self.become_pass, inject)
+        except:
+            # ignore password template errors, could be triggered by password charaters #10468
+            pass
 
         # make actual_user available as __magic__ ansible_ssh_user variable
         inject['ansible_ssh_user'] = actual_user


Test patch:
Repository: ansible/ansible

Issue:
playbook sudo: yes roles are not executed as sudo.
Issue Type:

Bug

Ansible Version:  1.9.0.1 from ppa stable.

Environment:

Linux Ubuntu 12.04 host to Linux Debian wheezy target.

Summary:

playbook roles are not executed as sudo anymore.

Steps To Reproduce:

consider the following playbook working with 1.7.2 but no more working with the 1.9.0.1:

test.yml

```
- hosts: test
  roles:
    - role: addgroups
      sudo: yes
```

roles/addgroups/tasks/main.yml

```

---
- name: add toto group
  group: name=toto state=present
```

Expected Results:

add the test group without any failure.

Actual Results:

failed: [zoo] => {"failed": true, "name": "test"}
msg: groupadd: Permission denied.
groupadd: cannot lock /etc/group; try again later

digging into the verbose mode we can observe that the addgroups role is still called with sudo with older version i.e. 1.7.2 and not any more called with sudo with 1.9.0.1

1.7.2

```
u'/bin/sh -c \'sudo -k && sudo -H -S -p "[sudo via ansible, key=hgpjwxwhvkcrvjywzmwiwhxnnamxrfln] password: " -u root /bin/sh -c \'"\'"\'echo SUDO-SUCCESS-hgpjwxwhvkcrvjywzmwiwhxnnamxrfln; LANG=C LC_CTYPE=C /usr/bin/python /home/test/.ansible/tmp/ansible-tmp-1427390484.81-80330223816703/group\'"
```

1.9.0.1

```
/bin/sh -c 'LANG=C LC_CTYPE=C /usr/bin/python /home/test/.ansible/tmp/ansible-tmp-1427392790.43-74683051810820/group
```

Cheers



Discussion:
ugly workaround:
in roles/addgroups/tasks/main.yml

```
---
- name: add toto group
  group: name=toto state=present
  sudo: yes
```

:+1: 

A git bisect has led me to the following commit as where the problem was introduced: de5eae2007d4138730582e876770d3b24c863753

This also seems to affect task includes. The following seems to cause all included tasks to be sudo'ed on 1.8.4 but not 1.9.0.1:

```
  - include: mytasks.yml
    sudo: yes
```


Resolving patch:
diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -577,7 +577,7 @@ def _load_tasks(self, tasks, vars=None, role_params=None, default_vars=None, bec
 
             # evaluate privilege escalation vars for current and child tasks
             included_become_vars = {}
-            for k in ["become", "become_user", "become_method", "become_exe"]:
+            for k in ["become", "become_user", "become_method", "become_exe", "sudo", "su", "sudo_user", "su_user"]:
                 if k in x:
                     included_become_vars[k] = x[k]
                 elif k in become_vars:


Test patch:
Repository: ansible/ansible

Issue:
Lineinfile backup doesn't work on FAT32
##### Issue Type:

Bug Report
##### Ansible Version:

```
ansible 1.9.0.1
  configured module search path = None
```
##### Environment:

Running on Arch Linux, managing Raspbian on a Raspberry Pi.
##### Summary:

When using the lineinfile module with backup=yes on a FAT32 file system, I get an exception.

It appears that some of the characters (I think at least the colon in the timestamp) are invalid on FAT32.
##### Steps To Reproduce:

I used the following task:

``` yaml
- name: Enable systemd.
  lineinfile:
    dest: /boot/cmdline.txt
    state: present
    regexp: '^(.* rootwait)$'
    line: '\1 init=/bin/systemd'
    backrefs: yes
    backup: yes
```
##### Expected Results:

It works :)
##### Actual Results:

``` python
Traceback (most recent call last):
  File "<stdin>", line 2199, in <module>
  File "<stdin>", line 394, in main
  File "<stdin>", line 281, in present
  File "<stdin>", line 1706, in backup_local
  File "/usr/lib/python2.7/shutil.py", line 130, in copy2
    copyfile(src, dst)
  File "/usr/lib/python2.7/shutil.py", line 83, in copyfile
    with open(dst, 'wb') as fdst:
IOError: [Errno 22] invalid mode ('wb') or filename: '/boot/cmdline.txt.2015-04-01@14:28:29~'
```



Discussion:
A possible fix would be to use a unix timestamp or alternatively `20150401142829` instead. Might this introduce reverse compatibility issues of some form?

This code could also live in a try-except block.

many of our file operations will fail on non POSIX file systems, still this should not be a traceback

This is very simple to fix though. So I think it's worth the effort :)

Alternatively, a way to specify the destination path for the backup file would be even better.

it is already in a try block, it does not capture IOErrors though, which it should.

as for this being a 'simple' fix, yes, if we wan't to break backwards compatibility, it is simple, but we don't.


Resolving patch:
diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py
--- a/lib/ansible/module_utils/basic.py
+++ b/lib/ansible/module_utils/basic.py
@@ -1303,7 +1303,7 @@ def backup_local(self, fn):
 
         try:
             shutil.copy2(fn, backupdest)
-        except shutil.Error, e:
+        except (shutil.Error, IOError), e:
             self.fail_json(msg='Could not make backup of %s to %s: %s' % (fn, backupdest, e))
         return backupdest
 


Test patch: