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

win_environment : Maybe add an option to read variable content ? #605

Open
freeeflyer opened this issue Apr 18, 2024 · 6 comments
Open

win_environment : Maybe add an option to read variable content ? #605

freeeflyer opened this issue Apr 18, 2024 · 6 comments

Comments

@freeeflyer
Copy link

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

@jborean93
Copy link
Collaborator

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.

@freeeflyer
Copy link
Author

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 ?

@jborean93
Copy link
Collaborator

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.

@chspnk
Copy link

chspnk commented Jun 24, 2024

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
    }

@jborean93
Copy link
Collaborator

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

@chspnk
Copy link

chspnk commented Jul 24, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants