diff --git a/lib/ansible/modules/windows/win_eventlog.ps1 b/lib/ansible/modules/windows/win_eventlog.ps1 new file mode 100644 index 00000000000..fc993e2fde7 --- /dev/null +++ b/lib/ansible/modules/windows/win_eventlog.ps1 @@ -0,0 +1,302 @@ +#!powershell + +# (c) 2017, Andrew Saraceni +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# WANT_JSON +# POWERSHELL_COMMON + +$ErrorActionPreference = "Stop" + +function Get-EventLogDetail { + <# + .SYNOPSIS + Get details of an event log, sources, and associated attributes. + Used for comparison against passed-in option values to ensure idempotency. + #> + param( + [String]$LogName + ) + + $log_details = @{} + $log_details.name = $LogName + $log_details.exists = $false + $log = Get-EventLog -List | Where-Object {$_.Log -eq $LogName} + + if ($log) { + $log_details.exists = $true + $log_details.maximum_size_kb = $log.MaximumKilobytes + $log_details.overflow_action = $log.OverflowAction.ToString() + $log_details.retention_days = $log.MinimumRetentionDays + $log_details.entries = $log.Entries.Count + $log_details.sources = [Ordered]@{} + + # Retrieve existing sources and category/message/parameter file locations + # Associating file locations and sources with logs can only be done from the registry + + $root_key = "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\{0}" -f $LogName + $log_root = Get-ChildItem -Path $root_key + + foreach ($child in $log_root) { + $source_name = $child.PSChildName + $log_details.sources.$source_name = @{} + $hash_cursor = $log_details.sources.$source_name + + $source_root = "{0}\{1}" -f $root_key, $source_name + $resource_files = Get-ItemProperty -Path $source_root + + $hash_cursor.category_file = $resource_files.CategoryMessageFile + $hash_cursor.message_file = $resource_files.EventMessageFile + $hash_cursor.parameter_file = $resource_files.ParameterMessageFile + } + } + + return $log_details +} + +function Test-SourceExistence { + <# + .SYNOPSIS + Get information on a source's existence. + Examine existence regarding the parent log it belongs to and its expected state. + #> + param( + [String]$LogName, + [String]$SourceName, + [Switch]$NoLogShouldExist + ) + + $source_exists = [System.Diagnostics.EventLog]::SourceExists($SourceName) + + if ($source_exists -and $NoLogShouldExist) { + Fail-Json -obj $result -message "Source $SourceName already exists and cannot be created" + } + elseif ($source_exists) { + $source_log = [System.Diagnostics.EventLog]::LogNameFromSourceName($SourceName, ".") + if ($source_log -ne $LogName) { + Fail-Json -obj $result -message "Source $SourceName does not belong to log $LogName and cannot be modified" + } + } + + return $source_exists +} + +function ConvertTo-MaximumSize { + <# + .SYNOPSIS + Convert a string KB/MB/GB value to common bytes and KB representations. + .NOTES + Size must be between 64KB and 4GB and divisible by 64KB, as per the MaximumSize parameter of Limit-EventLog. + #> + param( + [String]$Size + ) + + $parsed_size = @{ + bytes = $null + KB = $null + } + + $size_regex = "^\d+(\.\d+)?(KB|MB|GB)$" + if ($Size -notmatch $size_regex) { + Fail-Json -obj $result -message "Maximum size $Size is not properly specified" + } + + $size_upper = $Size.ToUpper() + $size_numeric = [Double]$Size.Substring(0, $Size.Length -2) + + if ($size_upper.EndsWith("GB")) { + $size_bytes = $size_numeric * 1GB + } + elseif ($size_upper.EndsWith("MB")) { + $size_bytes = $size_numeric * 1MB + } + elseif ($size_upper.EndsWith("KB")) { + $size_bytes = $size_numeric * 1KB + } + + if (($size_bytes -lt 64KB) -or ($size_bytes -ge 4GB)) { + Fail-Json -obj $result -message "Maximum size must be between 64KB and 4GB" + } + elseif (($size_bytes % 64KB) -ne 0) { + Fail-Json -obj $result -message "Maximum size must be divisible by 64KB" + } + + $parsed_size.bytes = $size_bytes + $parsed_size.KB = $size_bytes / 1KB + return $parsed_size +} + +$params = Parse-Args $args -supports_check_mode $true +$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false + +$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true +$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","clear","absent" +$sources = Get-AnsibleParam -obj $params -name "sources" -type "list" +$category_file = Get-AnsibleParam -obj $params -name "category_file" -type "path" +$message_file = Get-AnsibleParam -obj $params -name "message_file" -type "path" +$parameter_file = Get-AnsibleParam -obj $params -name "parameter_file" -type "path" +$maximum_size = Get-AnsibleParam -obj $params -name "maximum_size" -type "str" +$overflow_action = Get-AnsibleParam -obj $params -name "overflow_action" -type "str" -validateset "OverwriteOlder","OverwriteAsNeeded","DoNotOverwrite" +$retention_days = Get-AnsibleParam -obj $params -name "retention_days" -type "int" + +$result = @{ + changed = $false + name = $name + sources_changed = @() +} + +$log_details = Get-EventLogDetail -LogName $name + +# Handle common error cases up front +if ($state -eq "present" -and !$log_details.exists -and !$sources) { + # When creating a log, one or more sources must be passed + Fail-Json -obj $result -message "You must specify one or more sources when creating a log for the first time" +} +elseif ($state -eq "present" -and $log_details.exists -and $name -in $sources -and ($category_file -or $message_file -or $parameter_file)) { + # After a default source of the same name is created, it cannot be modified without removing the log + Fail-Json -obj $result -message "Cannot modify default source $name of log $name - you must remove the log" +} +elseif ($state -eq "clear" -and !$log_details.exists) { + Fail-Json -obj $result -message "Cannot clear log $name as it does not exist" +} +elseif ($state -eq "absent" -and $name -in $sources) { + # You also cannot remove a default source for the log - you must remove the log itself + Fail-Json -obj $result -message "Cannot remove default source $name from log $name - you must remove the log" +} + +try { + switch ($state) { + "present" { + foreach ($source in $sources) { + if ($log_details.exists) { + $source_exists = Test-SourceExistence -LogName $name -SourceName $source + } + else { + $source_exists = Test-SourceExistence -LogName $name -SourceName $source -NoLogShouldExist + } + + if ($source_exists) { + $category_change = $category_file -and $log_details.sources.$source.category_file -ne $category_file + $message_change = $message_file -and $log_details.sources.$source.message_file -ne $message_file + $parameter_change = $parameter_file -and $log_details.sources.$source.parameter_file -ne $parameter_file + # Remove source and recreate later if any of the above are true + if ($category_change -or $message_change -or $parameter_change) { + Remove-EventLog -Source $source -WhatIf:$check_mode + } + else { + continue + } + } + + $new_params = @{ + LogName = $name + Source = $source + } + if ($category_file) { + $new_params.CategoryResourceFile = $category_file + } + if ($message_file) { + $new_params.MessageResourceFile = $message_file + } + if ($parameter_file) { + $new_params.ParameterResourceFile = $parameter_file + } + + if (!$check_mode) { + New-EventLog @new_params + $result.sources_changed += $source + } + $result.changed = $true + } + + if ($maximum_size) { + $converted_size = ConvertTo-MaximumSize -Size $maximum_size + } + + $size_change = $maximum_size -and $log_details.maximum_size_kb -ne $converted_size.KB + $overflow_change = $overflow_action -and $log_details.overflow_action -ne $overflow_action + $retention_change = $retention_days -and $log_details.retention_days -ne $retention_days + + if ($size_change -or $overflow_change -or $retention_change) { + $limit_params = @{ + LogName = $name + WhatIf = $check_mode + } + if ($maximum_size) { + $limit_params.MaximumSize = $converted_size.bytes + } + if ($overflow_action) { + $limit_params.OverflowAction = $overflow_action + } + if ($retention_days) { + $limit_params.RetentionDays = $retention_days + } + + Limit-EventLog @limit_params + $result.changed = $true + } + + } + "clear" { + if ($log_details.entries -gt 0) { + Clear-EventLog -LogName $name -WhatIf:$check_mode + $result.changed = $true + } + } + "absent" { + if ($sources -and $log_details.exists) { + # Since sources were passed, remove sources tied to event log + foreach ($source in $sources) { + $source_exists = Test-SourceExistence -LogName $name -SourceName $source + if ($source_exists) { + Remove-EventLog -Source $source -WhatIf:$check_mode + if (!$check_mode) { + $result.sources_changed += $source + } + $result.changed = $true + } + } + } + elseif ($log_details.exists) { + # Only name passed, so remove event log itself (which also removes contained sources) + Remove-EventLog -LogName $name -WhatIf:$check_mode + if (!$check_mode) { + $log_details.sources.GetEnumerator() | ForEach-Object { $result.sources_changed += $_.Name } + } + $result.changed = $true + } + } + } +} +catch { + Fail-Json -obj $result -message $_.Exception.Message +} + +$final_log_details = Get-EventLogDetail -LogName $name +foreach ($final_log_detail in $final_log_details.GetEnumerator()) { + if ($final_log_detail.Name -eq "sources") { + $sources = @() + $final_log_detail.Value.GetEnumerator() | ForEach-Object { $sources += $_.Name } + $result.$($final_log_detail.Name) = [Array]$sources + } + else { + $result.$($final_log_detail.Name) = $final_log_detail.Value + } +} + +Exit-Json -obj $result diff --git a/lib/ansible/modules/windows/win_eventlog.py b/lib/ansible/modules/windows/win_eventlog.py new file mode 100644 index 00000000000..39dc176d454 --- /dev/null +++ b/lib/ansible/modules/windows/win_eventlog.py @@ -0,0 +1,175 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Andrew Saraceni +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# this is a windows documentation stub. actual code lives in the .ps1 +# file of the same name + +ANSIBLE_METADATA = {'metadata_version': '1.0', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: win_eventlog +version_added: "2.4" +short_description: Manage Windows event logs +description: + - Allows the addition, clearing and removal of local Windows event logs, + and the creation and removal of sources from a given event log. Also + allows the specification of settings per log and source. +options: + name: + description: + - Name of the event log to manage. + required: true + state: + description: + - Desired state of the log and/or sources. + - When C(sources) is populated, state is checked for sources. + - When C(sources) is not populated, state is checked for the specified log itself. + - If C(state) is C(clear), event log entries are cleared for the target log. + choices: + - present + - clear + - absent + default: present + sources: + description: + - A list of one or more sources to ensure are present/absent in the log. + - When C(category_file), C(message_file) and/or C(parameter_file) are specified, + these values are applied across all sources. + category_file: + description: + - For one or more sources specified, the path to a custom category resource file. + message_file: + description: + - For one or more sources specified, the path to a custom event message resource file. + parameter_file: + description: + - For one or more sources specified, the path to a custom parameter resource file. + maximum_size: + description: + - The maximum size of the event log. + - Value must be between 64KB and 4GB, and divisible by 64KB. + - Size can be specified in KB, MB or GB (e.g. 128KB, 16MB, 2.5GB). + overflow_action: + description: + - The action for the log to take once it reaches its maximum size. + - For C(OverwriteOlder), new log entries overwrite those older than the C(retention_days) value. + - For C(OverwriteAsNeeded), each new entry overwrites the oldest entry. + - For C(DoNotOverwrite), all existing entries are kept and new entries are not retained. + choices: + - OverwriteOlder + - OverwriteAsNeeded + - DoNotOverwrite + retention_days: + description: + - The minimum number of days event entries must remain in the log. + - This option is only used when C(overflow_action) is C(OverwriteOlder). +author: + - Andrew Saraceni (@andrewsaraceni) +''' + +EXAMPLES = r''' +- name: Add a new event log with two custom sources + win_eventlog: + name: MyNewLog + sources: + - NewLogSource1 + - NewLogSource2 + state: present + +- name: Change the category and message resource files used for NewLogSource1 + win_eventlog: + name: MyNewLog + sources: + - NewLogSource1 + category_file: C:\NewApp\CustomCategories.dll + message_file: C:\NewApp\CustomMessages.dll + state: present + +- name: Change the maximum size and overflow action for MyNewLog + win_eventlog: + name: MyNewLog + maximum_size: 16MB + overflow_action: DoNotOverwrite + state: present + +- name: Clear event entries for MyNewLog + win_eventlog: + name: MyNewLog + state: clear + +- name: Remove NewLogSource2 from MyNewLog + win_eventlog: + name: MyNewLog + sources: + - NewLogSource2 + state: absent + +- name: Remove MyNewLog and all remaining sources + win_eventlog: + name: MyNewLog + state: absent +''' + +RETURN = r''' +name: + description: The name of the event log. + returned: always + type: string + sample: MyNewLog +exists: + description: Whether the event log exists or not. + returned: success + type: boolean + sample: true +entries: + description: The count of entries present in the event log. + returned: success + type: int + sample: 50 +maximum_size_kb: + description: Maximum size of the log in KB. + returned: success + type: int + sample: 512 +overflow_action: + description: The action the log takes once it reaches its maximum size. + returned: success + type: string + sample: OverwriteOlder +retention_days: + description: The minimum number of days entries are retained in the log. + returned: success + type: int + sample: 7 +sources: + description: A list of the current sources for the log. + returned: success + type: list + sample: ["MyNewLog", "NewLogSource1", "NewLogSource2"] +sources_changed: + description: A list of sources changed (e.g. re/created, removed) for the log; + this is empty if no sources are changed. + returned: always + type: list + sample: ["NewLogSource2"] +''' diff --git a/test/integration/targets/win_eventlog/aliases b/test/integration/targets/win_eventlog/aliases new file mode 100644 index 00000000000..c6d61981670 --- /dev/null +++ b/test/integration/targets/win_eventlog/aliases @@ -0,0 +1 @@ +windows/ci/group3 diff --git a/test/integration/targets/win_eventlog/tasks/main.yml b/test/integration/targets/win_eventlog/tasks/main.yml new file mode 100644 index 00000000000..5fec3ac34a3 --- /dev/null +++ b/test/integration/targets/win_eventlog/tasks/main.yml @@ -0,0 +1,10 @@ +- name: Run tests for win_eventlog in normal mode + include_tasks: tests.yml + vars: + in_check_mode: no + +- name: Run tests for win_eventlog in check-mode + include_tasks: tests.yml + vars: + in_check_mode: yes + check_mode: yes diff --git a/test/integration/targets/win_eventlog/tasks/tests.yml b/test/integration/targets/win_eventlog/tasks/tests.yml new file mode 100644 index 00000000000..b369362ee15 --- /dev/null +++ b/test/integration/targets/win_eventlog/tasks/tests.yml @@ -0,0 +1,447 @@ +# Test code for win_eventlog + +# (c) 2017, Andrew Saraceni +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +- name: Remove potentially leftover logs + win_eventlog: + name: "{{ item }}" + state: absent + with_items: + - WinEventLogTest + - NewWinEventLogTest + + +- name: Add log without sources + win_eventlog: + name: WinEventLogTest + state: present + register: add_log_without_sources + failed_when: add_log_without_sources.changed != false or add_log_without_sources.msg != "You must specify one or more sources when creating a log for the first time" + + +- name: Add log + win_eventlog: &wel_present + name: WinEventLogTest + sources: + - WinEventLogSource1 + - WinEventLogSource2 + state: present + register: add_log + +- name: Test add_log (normal mode) + assert: + that: + - add_log.changed == true + - add_log.exists == true + - add_log.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - add_log.sources_changed == ["WinEventLogSource1", "WinEventLogSource2"] + when: not in_check_mode + +- name: Test add_log (check-mode) + assert: + that: + - add_log.changed == true + - add_log.exists == false + - add_log.sources_changed == [] + when: in_check_mode + + +- name: Add log (again) + win_eventlog: *wel_present + register: add_log_again + +- name: Test add_log_again (normal mode) + assert: + that: + - add_log_again.changed == false + - add_log_again.exists == true + - add_log_again.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - add_log_again.sources_changed == [] + when: not in_check_mode + + +- name: Run tests for normal mode only (expects event log) + when: not in_check_mode + block: + + - name: Change default source + win_eventlog: + <<: *wel_present + sources: + - WinEventLogTest + category_file: C:\TestApp\AppCategories.dll + register: change_default_source + failed_when: change_default_source.changed != false or change_default_source.msg != "Cannot modify default source WinEventLogTest of log WinEventLogTest - you must remove the log" + + + - name: Change source category + win_eventlog: &welc_present + <<: *wel_present + sources: + - WinEventLogSource1 + category_file: C:\TestApp\AppCategories.dll + register: change_source_category + + - name: Test change_source_category + assert: + that: + - change_source_category.changed == true + - change_source_category.exists == true + - change_source_category.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_category.sources_changed == ["WinEventLogSource1"] + + + - name: Change source category (again) + win_eventlog: *welc_present + register: change_source_category_again + + - name: Test change_source_category_again + assert: + that: + - change_source_category_again.changed == false + - change_source_category_again.exists == true + - change_source_category_again.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_category_again.sources_changed == [] + + + - name: Change source message + win_eventlog: &welm_present + <<: *welc_present + message_file: C:\TestApp\AppMessages.dll + register: change_source_message + + - name: Test change_source_message + assert: + that: + - change_source_message.changed == true + - change_source_message.exists == true + - change_source_message.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_message.sources_changed == ["WinEventLogSource1"] + + + - name: Change source message (again) + win_eventlog: *welm_present + register: change_source_message_again + + - name: Test change_source_message_again + assert: + that: + - change_source_message_again.changed == false + - change_source_message_again.exists == true + - change_source_message_again.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_message_again.sources_changed == [] + + + - name: Change source parameter + win_eventlog: &welp_present + <<: *welm_present + parameter_file: C:\TestApp\AppParameters.dll + register: change_source_parameter + + - name: Test change_source_parameter + assert: + that: + - change_source_parameter.changed == true + - change_source_parameter.exists == true + - change_source_parameter.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_parameter.sources_changed == ["WinEventLogSource1"] + + + - name: Change source parameter (again) + win_eventlog: *welp_present + register: change_source_parameter_again + + - name: Test change_source_parameter_again + assert: + that: + - change_source_parameter_again.changed == false + - change_source_parameter_again.exists == true + - change_source_parameter_again.sources == ["WinEventLogSource1", "WinEventLogSource2", "WinEventLogTest"] + - change_source_parameter_again.sources_changed == [] + + + - name: Change log maximum size + win_eventlog: &wels_present + <<: *wel_present + maximum_size: 256MB + register: change_log_maximum_size + + - name: Test change_log_maximum_size + assert: + that: + - change_log_maximum_size.changed == true + - change_log_maximum_size.exists == true + - change_log_maximum_size.maximum_size_kb == 262144 + + + - name: Change log maximum size (again) + win_eventlog: *wels_present + register: change_log_maximum_size_again + + - name: Test change_log_maximum_size_again + assert: + that: + - change_log_maximum_size_again.changed == false + - change_log_maximum_size_again.exists == true + - change_log_maximum_size_again.maximum_size_kb == 262144 + + + - name: Change log invalid maximum size 1 + win_eventlog: + <<: *wel_present + maximum_size: 256 MB + register: change_log_invalid_maximum_size_1 + failed_when: change_log_invalid_maximum_size_1.changed != false or change_log_invalid_maximum_size_1.msg != "Maximum size 256 MB is not properly specified" + + + - name: Change log invalid maximum size 2 + win_eventlog: + <<: *wel_present + maximum_size: 5GB + register: change_log_invalid_maximum_size_2 + failed_when: change_log_invalid_maximum_size_2.changed != false or change_log_invalid_maximum_size_2.msg != "Maximum size must be between 64KB and 4GB" + + + - name: Change log invalid maximum size 3 + win_eventlog: + <<: *wel_present + maximum_size: 129KB + register: change_log_invalid_maximum_size_3 + failed_when: change_log_invalid_maximum_size_3.changed != false or change_log_invalid_maximum_size_3.msg != "Maximum size must be divisible by 64KB" + + + - name: Change log retention days + win_eventlog: &welr_present + <<: *wels_present + retention_days: 128 + register: change_log_retention_days + + - name: Test change_log_retention_days + assert: + that: + - change_log_retention_days.changed == true + - change_log_retention_days.exists == true + - change_log_retention_days.retention_days == 128 + + + - name: Change log retention days (again) + win_eventlog: *welr_present + register: change_log_retention_days_again + + - name: Test change_log_retention_days_again + assert: + that: + - change_log_retention_days_again.changed == false + - change_log_retention_days_again.exists == true + - change_log_retention_days_again.retention_days == 128 + + + - name: Change log overflow action + win_eventlog: &welo_present + <<: *wels_present + overflow_action: OverwriteAsNeeded + register: change_log_overflow_action + + - name: Test change_log_overflow_action + assert: + that: + - change_log_overflow_action.changed == true + - change_log_overflow_action.exists == true + - change_log_overflow_action.overflow_action == "OverwriteAsNeeded" + + + - name: Change log overflow action (again) + win_eventlog: *welo_present + register: change_log_overflow_action_again + + - name: Test change_log_overflow_action_again + assert: + that: + - change_log_overflow_action_again.changed == false + - change_log_overflow_action_again.exists == true + - change_log_overflow_action_again.overflow_action == "OverwriteAsNeeded" + + + - name: Add log with existing source + win_eventlog: &wele_present + name: NewWinEventLogTest + sources: + - WinEventLogSource1 + state: present + register: add_log_with_existing_source + failed_when: add_log_with_existing_source.changed != false or add_log_with_existing_source.msg != "Source WinEventLogSource1 already exists and cannot be created" + + + - name: Add new log + win_eventlog: + <<: *wele_present + sources: + - NewWinEventLogSource1 + + - name: Change source for different log + win_eventlog: + <<: *wele_present + sources: + - WinEventLogSource1 + category_file: C:\TestApp\AppCategories.dll + register: change_source_for_different_log + failed_when: change_source_for_different_log.changed != false or change_source_for_different_log.msg != "Source WinEventLogSource1 does not belong to log NewWinEventLogTest and cannot be modified" + + - name: Remove new log + win_eventlog: + name: NewWinEventLogTest + state: absent + + + - name: Add entry to log + win_shell: Write-EventLog -LogName WinEventLogTest -Source WinEventLogSource1 -EntryType Information -EventId 12345 -Message "Test message" + + - name: Verify add entry + win_eventlog: + name: WinEventLogTest + state: present + register: verify_add_entry + + - name: Test verify_add_entry + assert: + that: + - verify_add_entry.changed == false + - verify_add_entry.exists == true + - verify_add_entry.entries == 1 + + + - name: Clear log + win_eventlog: &wel_clear + name: WinEventLogTest + state: clear + register: clear_log + + - name: Test clear_log + assert: + that: + - clear_log.changed == true + - clear_log.exists == true + - clear_log.entries == 0 + when: not in_check_mode + + + - name: Clear log (again) + win_eventlog: *wel_clear + register: clear_log_again + + - name: Test clear_log_again + assert: + that: + - clear_log_again.changed == false + - clear_log_again.exists == true + - clear_log_again.entries == 0 + when: in_check_mode + + +- name: Clear absent log + win_eventlog: + name: WinEventLogTest + state: clear + register: clear_absent_log + when: in_check_mode + failed_when: clear_absent_log.changed != false or clear_absent_log.msg != "Cannot clear log WinEventLogTest as it does not exist" + + +- name: Remove default source + win_eventlog: &weld_absent + name: WinEventLogTest + sources: + - WinEventLogTest + state: absent + register: remove_default_source + failed_when: remove_default_source.changed != false or remove_default_source.msg != "Cannot remove default source WinEventLogTest from log WinEventLogTest - you must remove the log" + + +- name: Remove source + win_eventlog: &wels_absent + <<: *weld_absent + sources: + - WinEventLogSource1 + register: remove_source + +- name: Test remove_source (normal mode) + assert: + that: + - remove_source.changed == true + - remove_source.exists == true + - remove_source.sources == ["WinEventLogSource2", "WinEventLogTest"] + - remove_source.sources_changed == ["WinEventLogSource1"] + when: not in_check_mode + +- name: Test remove_source (check-mode) + assert: + that: + - remove_source.changed == false + - remove_source.exists == false + - remove_source.sources_changed == [] + when: in_check_mode + + +- name: Remove source (again) + win_eventlog: *wels_absent + register: remove_source_again + +- name: Test remove_source_again (normal mode) + assert: + that: + - remove_source_again.changed == false + - remove_source_again.exists == true + - remove_source.sources == ["WinEventLogSource2", "WinEventLogTest"] + - remove_source_again.sources_changed == [] + when: not in_check_mode + + +- name: Remove log + win_eventlog: &wel_absent + name: WinEventLogTest + state: absent + register: remove_log + +- name: Test remove_log (normal mode) + assert: + that: + - remove_log.changed == true + - remove_log.exists == false + - remove_log.sources_changed == ["WinEventLogSource2", "WinEventLogTest"] + when: not in_check_mode + +- name: Test remove_log (check-mode) + assert: + that: + - remove_log.changed == false + - remove_log.exists == false + - remove_log.sources_changed == [] + when: in_check_mode + + +- name: Remove log (again) + win_eventlog: *wel_absent + register: remove_log_again + +- name: Test remove_log_again (normal mode) + assert: + that: + - remove_log_again.changed == false + - remove_log_again.exists == false + - remove_log_again.sources_changed == [] + when: not in_check_mode