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_timezone - Upgrade to Ansible.Basic style #705

Merged
merged 1 commit into from
Dec 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 60 additions & 56 deletions plugins/modules/win_timezone.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,75 @@
# Copyright: (c) 2015, Phil Schwartz <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

#Requires -Module Ansible.ModuleUtils.Legacy
#AnsibleRequires -CSharpUtil Ansible.Basic
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This newer requires statement is used by Ansible to load in the Ansible.Basic C# module util.


$params = Parse-Args $args -supports_check_mode $true
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$diff_support = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
$spec = @{
options = @{
timezone = @{
required = $true
type = "str"
}
}
supports_check_mode = $true
}

$timezone = Get-AnsibleParam -obj $params -name "timezone" -type "str" -failifempty $true
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)

$result = @{
changed = $false
previous_timezone = $timezone
timezone = $timezone
}
$timezone = $module.Params.timezone
Comment on lines +8 to +20
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Instead of using Parse-Args and Get-AnsibleParam we define the argument spec inside a hashtable, create the module object, then retrieve the module options through $module.Params.x. The $spec is the module option specification and this module only has 1 option called timezone that is required and is typed as a string.

We also explicitly have to opt into saying we support check mode with supports_check_mode = $true in the root of the spec hashtable. Without this the module will be skipped when running under check mode.


Try {
# Get the current timezone set
$result.previous_timezone = $(tzutil.exe /g)
If ($LASTEXITCODE -ne 0) {
Throw "An error occurred when getting the current machine's timezone setting."
}
$module.Result.previous_timezone = $null
$module.Result.timezone = $timezone
Comment on lines +22 to +23
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The module result is located under $module.Result. We assign the return values accordingly.


if ( $result.previous_timezone -eq $timezone ) {
Exit-Json $result "Timezone '$timezone' is already set on this machine"
}
Else {
# Check that timezone is listed as an available timezone to the machine
$tzList = $(tzutil.exe /l).ToLower()
If ($LASTEXITCODE -ne 0) {
Throw "An error occurred when listing the available timezones."
}
Function Invoke-TzUtil {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[object]
$Module,

$tzExists = $tzList.Contains(($timezone -Replace '_dstoff').ToLower())
if (-not $tzExists) {
Fail-Json $result "The specified timezone: $timezone isn't supported on the machine."
}
[Parameter(Mandatory)]
[string]
$Action,

if ($check_mode) {
$result.changed = $true
}
else {
tzutil.exe /s "$timezone"
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred when setting the specified timezone with tzutil."
}

$new_timezone = $(tzutil.exe /g)
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred when getting the current machine's timezone setting."
}

if ($timezone -eq $new_timezone) {
$result.changed = $true
}
}
[Parameter(ValueFromRemainingArguments)]
[string[]]
$ArgumentList
)

if ($diff_support) {
$result.diff = @{
before = "$($result.previous_timezone)`n"
after = "$timezone`n"
}
}
$stdout = $null
$stderr = . { tzutil.exe @ArgumentList | Set-Variable -Name stdout } 2>&1 | ForEach-Object ToString

if ($LASTEXITCODE) {
$Module.Result.stdout = $stdout -join "`n"
$Module.Result.stderr = $stderr -join "`n"
$Module.Result.rc = $LASTEXITCODE
$Module.FailJson("An error occurred when $Action.")
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Instead of Fail-Json $result "msg" we now do $module.FailJson("msg"). The result is already stored in the module object so we just need to supply the error message to fail with.

$module.FailJson() will automatically exit the module and set it as failed.

}

$stdout
}

# Get the current timezone set
$previousTz = Invoke-TzUtil /g -Module $module -Action "getting the current machine's timezone setting"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The Invoke-TzUtil is merely a helper function and isn't strictly related to using the Ansible.Basic style. I just saw this module called tzutil.exe multiple times and was checking the result before failing if it wasn't 0. So instead of duplicating those checks I put it in one function and have that handle all the error handling.

$module.Result.previous_timezone = $previousTz

if ($module.DiffMode) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We use $module.DiffMode to check if --diff is enabled for the task. This isn't strictly necessary but it avoids sending extra data back to Ansible.

$module.Diff.before = "$previousTz`n"
$module.Diff.after = "$timezone`n"
Comment on lines +59 to +60
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Instead of diff being part of the result, it's stored under a specific property $module.Diff. The structure is the same as before where we typically return a before and after with the changes involved.

}
Catch {
Fail-Json $result "Error setting timezone to: $timezone."

if ($previousTz -ne $timezone) {
# Check that timezone is listed as an available timezone to the machine
$tzList = Invoke-TzUtil /l -Module $module -Action "listing the available timezones"

if ($tzList -notcontains ($timezone -replace '_dstoff')) {
$module.FailJson("The specified timezone: $timezone isn't supported on the machine.")
}

if (-not $module.CheckMode) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

$module.CheckMode is a boolean that is true when we are running in check mode. Basically we want to avoid making any actual changes while in check mode.

$null = Invoke-TzUtil /s $timezone -Module $module -Action "setting the specified timezone"
}
$module.Result.changed = $true
}

Exit-Json $result
$module.ExitJson()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Instead of Exit-Json $result we just do $module.ExitJson(). The result is already stored on the $module object so we don't have to provide it separately. This will stop the module and return the data in the result.

Loading