ansible.windows
ansible.windows copied to clipboard
win_environment : Maybe add an option to read variable content ?
SUMMARY
win_environment only modify var. We could add an option to return the current value.
ISSUE TYPE
- Feature Idea
COMPONENT NAME
We could only return the value when no actual value is given
ADDITIONAL INFORMATION
- name: Set an environment variable for all users
ansible.windows.win_environment:
state: present
name: TestVariable
Return value of TestVariable
I don't see a real benefit of doing this over a simple call to setup
to get the builtin facts or just doing a win_shell
command to get the env var you need.
- hosts: windows
gather_facts: false
tasks:
- name: Gather all env vars
setup:
gather_subset: env
- name: Display env var through facts
debug:
var: ansible_env['SystemRoot']
- name: get env var through win_shell
win_shell: $env:SystemRoot
register: shell_res
changed_when: False
- name: Display env var through win_shell
debug:
var: shell_res.stdout | trim # Or shell_res.stdout_lines[0]
The ansible_env/ansible_facts['env']
option will actually be automatically retrieved if you haven't disabled fact gathering by default. It's a bit heavy handed but it does retrieve all the env vars. The win_shell
example is a bit simpler as you are just retrieving an env var on demand, the only two caveats are that you need to do changed_when: False
on the task if you care about reported changes and access the value through shell_res.stdout | trim
or shell_res.stdout_lines[0]
.
We try to avoid having modules that both set a state and get a state in favour of separate modules. While we do have some today that do that it's more of a historical thing that happened before we put those rules in place.
We try to avoid having modules that both set a state and get a state in favour of separate modules. While we do have some today that do that it's more of a historical thing that happened before we put those rules in place.
Why is that ?
It makes the module development a lot easier to handle as they stay dedicated to one task and one task only. For example
- You no longer have to deal with returning values that could differ if you are in check mode or not after making a change
- The module's documentation is no longer as complex, it's easier to document options that are required all the time rather than if x is set to y and so on
- It more easily allows us to expose filtering options as part of the module options, trying to do that in a module that also makes changes complicated the UX and makes things more confusing for people
While yes this is a pretty simple thing to add support for I don't believe the benefits outweigh the extra complexity in the code, especially since the setup
module already retrieves all env vars and you can get your own env var with a simple win_shell
task.
While I understand (and agree) what @jborean93 states regarding the single purpose/responsibility of a module, I would like to add that for me ansible_env['PATH']
is not an alternative, as I need the content of the PATH
variable on machine level. Apparently ansible_env['PATH']
returns the user level variable.
So my question is: How could I achieve this other than using a PowerShell script (which is what I do now)? Maybe I'm missing something here..
Thanks for your reply!
If anyone is interested this is what I do now (don't hit me 🙃):
- name: Ensure OpenSSL is in the system PATH
vars:
win_openssl_bin_path: 'C:\Program Files\OpenSSL\bin'
register: win_openssl_path_change
changed_when: win_openssl_path_change.rc == 2
failed_when: win_openssl_path_change.rc not in [0, 2]
ansible.windows.win_shell: |
# Get the current system PATH environment variable
$newPath = "{{ win_openssl_bin_path }}"
$currentPath = [System.Environment]::GetEnvironmentVariable('PATH', [System.EnvironmentVariableTarget]::Machine)
# Check if the new path is already in the PATH variable
if ($currentPath -like "*$newPath*") {
Write-Output "PATH already contains $newPath"
Write-Output "PATH=$currentPath"
Exit 0 # Indicates no change
} else {
# Append the new path to the PATH variable
$updatedPath = "$currentPath;$newPath"
[System.Environment]::SetEnvironmentVariable('PATH', $updatedPath, [System.EnvironmentVariableTarget]::Machine)
Write-Output "PATH updated to include $newPath"
Write-Output "PATH=$updatedPath"
Exit 2 # Indicates that PATH was changed
}
Short of using a win_shell
or win_powershell
code to get the result there's no module right now that can get the machine or user level scoped env var values. This sort of functionality would be best added as a new module like win_environment_info
which can retrieve this information.
Getting values for specific scopes is a bit of a niche scenario as typically you just set the value rather than get the value. In your particular example you can just use ansible.windows.win_path to idempotently set the PATH
env var saving you all this complexity.
- ansible.windows.win_path:
name: PATH
elements:
- C:\Program Files\OpenSSL\bin
# scope: user # Uncomment if you want this on the suer scope
Thanks so much, @jborean93. Apparently that's what I was missing as this seems to do exactly what I need. I wonder why I wasn't able to find that before... m( Sorry for the inconvenience and thanks for your kind reply.